Commit Graph
1442 Commits
Author SHA1 Message Date
maxjivi05 aefd8a3b60 fix(xbox): report a failed class registration in the launch log 2026-10-24 11:14:20 -04:00
maxjivi05 fee8ce91f3 fix(xbox): register the runtime's WinRT classes and load its wintypes so Minecraft starts 2026-10-24 11:14:20 -04:00
maxjivi05 bcb18e3fb7 fix(xbox): match only the 401 rejection Xodus prints 2026-10-24 09:07:13 -04:00
maxjivi05 6855dd4467 fix(xbox): say to sign in again when Microsoft rejects the download's licenses 2026-10-24 09:07:13 -04:00
maxjivi05 a66d7d74a4 fix: Steam Input mouse clicks, scrolling and pointer moves reach games again 2026-10-24 09:07:04 -04:00
Kurt Himebauch 2bd279a0f3 fix: read Steam shader settings off the main thread 2026-10-24 08:54:41 -04:00
maxjivi05 0790cb4390 fix: keep a Proton's originals when its folder could not be fully removed 2026-10-24 08:22:00 -04:00
maxjivi05 ad6d8d824a fix: removing a Proton also deletes its stored component originals 2026-10-24 08:22:00 -04:00
maxjivi05 0b671b2144 fix: match an annotated overlay header and keep the settings file's mode 2026-10-24 06:27:46 -04:00
maxjivi05 31cead9b32 fix: keep blank lines inside the overlay section and stage settings under a unique name 2026-10-24 06:27:46 -04:00
maxjivi05 26c3dcc885 fix: turn off the Ubisoft Connect overlay so Ubisoft games stop crashing at start 2026-10-24 06:27:46 -04:00
maxjivi05 476642be71 chore: drop the added comments 2026-10-24 01:42:20 -04:00
Nikolay Nadorichev 8c86b718a0 fix: find the signed-in Steam account when loginusers.vdf has no MostRecent
droiddeck-steam-shortcuts and AddedGames.accountConfig took the account
marked "MostRecent" in loginusers.vdf, else the only userdata folder.
The arm64 client here writes no MostRecent, so with two accounts in one
install nothing was picked: no added or store game reached
shortcuts.vdf ("no signed-in account yet; nothing written") and Steam
answered their launch with "App configuration unavailable".

Without MostRecent, take the account marked AutoLogin, then the one with
the latest timestamp. Both sides use the same order so the app reads the
config the guest script writes.
2026-10-24 01:42:20 -04:00
maxjivi05 473ac666b3 Take over Steam's Default startup movie pick 2026-10-24 01:41:08 -04:00
maxjivi05 f89dc04072 fix: Proton's EasyAntiCheat and BattlEye runtimes are not listed as games
Steam installs Proton EasyAntiCheat Runtime (1826330) and Proton BattlEye Runtime (1161040) as tool depots. The launcher's Games tab and the desktop's game entries now skip them like the other runtimes.
2026-10-24 00:47:45 -04:00
maxjivi05 dd79f44b3a fix: the Steam download monitor no longer stalls the main thread on a long content log
The content log was read with RandomAccessFile.readLine, one byte per read, on the main thread. A 4 MB log took about 2 s on the first poll, enough for an ANR on slower devices while a download runs. It is now read through a buffered reader with the same Latin-1 lines and offset, and the per-line regexes only run on lines that can match.
2026-10-24 00:27:22 -04:00
maxjivi05 b0e405ebf3 fix: Epic client imports get the launch command, versioned installs need a matching manifest build
Games the Epic client installed now carry their LaunchCommand arguments too, split by a new launch.split op. A doubled quote inside a quoted argument is one literal quote, and an install with a version ignores a manifest without the same build.
2026-10-23 23:59:37 -04:00
maxjivi05 42026b382f fix: keep manifest launch arguments to the installed build and their own additions
The manifest's arguments apply only when its build matches the installed version, only arguments the merge inserted are tracked as its own, escaped quotes split like a Windows command line, and the REDprelauncher rule needs Cyberpunk2077.exe beside it.
2026-10-23 23:59:37 -04:00
maxjivi05 8209a707f4 fix: Caravan SandWitch and Cyberpunk 2077 run at D3D12 feature level 12_1
Feature level 12_2 makes vkd3d-proton report mesh shaders and ray tracing that Turnip doesn't provide. Caravan SandWitch (Unreal Engine 5) then builds mesh shader pipelines without a pipeline layout and the driver crashes; Cyberpunk 2077 stops at ray tracing initialization. Only these two games get 12_1, and a value set in a game's own settings still wins.
2026-10-23 23:59:37 -04:00
maxjivi05 46cd8e1777 fix: Epic games get their manifest launch command
Epic manifests carry a launch command next to the launch executable, which the Epic launcher passes to the game. It was read and dropped, so Caravan SandWitch never got -PCStore=EGS and quit with "started outside of any known PC store". The manifest's launch command now joins the game's arguments, including for games already installed.
2026-10-23 23:59:37 -04:00
maxjivi05 6e1621fe53 fix: Steam's Ubisoft games install Ubisoft Connect again
The redistributable seeder marked every process in a game's install scripts as already run, so the Ubisoft Connect installer that Ubisoft games list was skipped and they stopped with "Unable to locate Uplay PC". It is now left to run like the Vulkan runtime installer, and a marker an earlier seeding wrote is taken back out.
2026-10-23 23:58:39 -04:00
XxJSONDeruloxX 546574e982 fix(xbox): enable proot fast path in Xodus 2026-10-23 23:56:24 -04:00
XxJSONDeruloxX b1ab55856e fix(ui): clear search focus and use store accents 2026-10-23 23:56:24 -04:00
XxJSONDeruloxX 4a0eb14d1f fix(xbox): mount selected SD library in Xodus 2026-10-23 23:56:24 -04:00
XxJSONDeruloxX 2c8ae3753c fix(xbox): mount external storage for downloads 2026-10-23 23:56:24 -04:00
Kurt Himebauch fcfbb74068 fix: one refused thermal or power query no longer drops the others from the session report (#991) 2026-10-23 23:43:01 -04:00
MaxsTechReview 0340be5a7d Steam client download: resumes, retries, shows megabytes, and isn't paused out of sight (#587)
A user's first Steam setup never finished on an Honor Pad (Snapdragon 6
Gen 1, metered Wi-Fi with a 14 Mbit/s link). Their log stops at
`downloading Steam: bins_linuxarm64_linuxarm64 (2/17)`. The log was
shared 31 s into the session, so nothing had failed yet. The way the
download works explains why it never got further.

## Why

- **The session pauses the download.** With the default background
behavior (Manual), a session pauses as soon as DroidDeck is hidden or
the screen turns off. In the user's log that happened one second after
start, before the download had begun.
- "Keep downloads running" doesn't help. It's off by default, and it
only recognizes Steam's own game downloads, not the runtime fetching the
client.
- A first run shows nothing for minutes, so leaving the app or letting
the screen time out is exactly what people do.
- **The download is bigger than the screen says.** The client is about
360 MB in 17 parts, and part 2 alone is 110 MB. The loading screen said
"~1-2 min" and counted parts, not bytes, so on a slow link it looks
frozen at about 5%.
- **Nothing handles a bad connection.** Each part was a plain `curl
-fsSL` with no timeout, no retry and no progress output.
  - A stalled connection could wait forever.
- A failed one ended the session and threw away everything fetched, so
the next try started from part 1.

## What changes

- **`droiddeck-steam-install`**:
- Parts go to `package/droiddeck-download` and stay there until the
client is installed.
  - Each part resumes from the bytes on disk (`curl -C -`).
  - A transfer under 4 KB/s for a minute is dropped and resumed.
- Attempts that make no progress back off 5–30 s, then give up with a
clear error. Whatever arrived is kept.
  - A finished part is marked unpacked, so a later session skips it.
- Bytes that fail their checksum are fetched whole again. A server that
won't resume starts the part over. Parts left over from another client
version are dropped.
- A repair redoes every part once, and keeps what an interrupted repair
already redid.
- Every 5 s the step line also carries megabytes overall: `… (2/17), 45
of 360 MB`.
- **Loading screen** (`LoadingState`): shows `Downloading the Steam
client · 45 / 360 MB`, with the bar following the bytes. Older runtimes
still show the part name.
- **`SessionService`**: until the session's first frame, the download
watch also checks whether the client is still to be fetched (no install
stamp or client binary, or a repair requested). While it is:
- the session stays awake with its wake and Wi-Fi locks, whatever the
downloads setting says;
  - the notification shows "Steam download active" with **Suspend now**;
  - a `steam.client_download` event marks start and end.
- The watch is set up before the first suspend decision, so a session
started with the screen off isn't paused first. Once the client is
there, the chosen behavior applies again.
- **`droiddeck-session`**: the step no longer promises 1–2 minutes.

## Testing

- `python3 -m unittest discover -s tools/tests -p 'test_*.py'`: 497 OK,
1 skipped.
- `test_steam_install.py` gets a fake curl that drops connections,
refuses to resume or fails on cue.
- New cases cover: megabyte progress; resuming after a dropped
connection; keeping finished and partial parts across a failed session;
restarting a part the server won't resume; re-fetching bad bytes;
dropping another version's parts; a repair resumed once.
- Kotlin: `:app:testDebugUnitTest --tests
'com.droiddeck.launcher.session.*'` passes. That includes the new
`LoadingStateTest` and the `clientInstallPending` cases in
`SteamDownloadMonitorTest`.
- RedMagic NP06J, with Background behavior set to Manual and "Keep
downloads running" off (the user's settings), and a client repair
requested:
- Started Steam and sent DroidDeck to the background straight away. The
client download stayed active for 30 s with no pause, and all 360 MB
arrived. Then the session paused as Manual should.
- Stopped a second repair during part 2. Part 1 was marked unpacked, the
110 MB part 2 was kept, and the repair marker stayed.
- Started again: it resumed at 110 of 360 MB, unpacked part 2 without
fetching it again, finished, and Steam started normally.
- The loading screen showed `Downloading the Steam client · 248 / 360
MB`.

Retested 2026-10-23 on the REDMAGIC tablet after merging main, which
brought in the stable-channel fallback. Background behavior was set to
Manual with "Keep downloads running" off. A client repair was forced,
then Home was pressed right after Start:

| Build | Session while hidden | Client download |
|---|---|---|
| main | suspended 1 s after Home | stuck at part 3/17 after 90 s |
| this PR | kept awake until the client was in | all 17 parts, 362 MB in
46 s with MB progress; suspended once done |

`tools.tests.test_steam_install` (22), `SteamDownloadMonitorTest` and
`LoadingStateTest` pass.

## Not changed

- **The download is the plain zips.** Valve's manifest also lists `.vz`
(LZMA) versions, 228 MB instead of 360 MB. Using them needs a VZ decoder
in the guest; that could be a follow-up.
- **The stall and retry path** is covered by the tests but wasn't forced
on the device.
2026-10-23 23:28:05 -04:00
maxjivi05 132f40ac97 fix: install step progress cannot overflow 2026-10-23 23:11:34 -04:00
maxjivi05 5981bbb1e2 fix: an oversized install step count falls back to the step text 2026-10-23 22:51:28 -04:00
maxjivi05 7419ba114f fix: the client install stays awake until Steam's first frame and its end is recorded 2026-10-23 22:22:14 -04:00
maxjivi05 96e2bf992d fix: an HTTP 4xx part hands over to the next CDN at once 2026-10-23 21:20:50 -04:00
Kurt Himebauch ad9eb8eb29 xbox backend x86 to arm cross compilation (#1440) 2026-10-23 21:02:20 -04:00
MaxsTechReview 116d0e4f1a fix: a game started from another launcher returns to that launcher (#1438)
A game started from another launcher (ES-DE, a `droiddeck://game/` link,
a pinned shortcut) should send the player back to that launcher when it
closes. Instead DroidDeck always opened the Android home screen, which
is a different place whenever that launcher isn't the default Home app.

## Cause
The link is handled by `FrontEndActivity`, which starts the session in
its own task and stays behind it in a second DroidDeck task. When the
session ended, DroidDeck started `CATEGORY_HOME` to cover that leftover
task, so the player always landed on the system Home.

## Fix
When a link-launched session ends, `SessionActivity` removes the task
that handled the link (a `FrontEndActivity` task whose base intent is a
game link), then removes its own task. Android then shows whatever was
underneath: ES-DE, any other app that launched the game, or Home when
Home launched it.

Sessions started from DroidDeck's own Games tab are unchanged.

## Testing
On a REDMAGIC NP06J, with the `droiddeck://game/945360` link started
using ES-DE's flags (`NEW_TASK | CLEAR_TASK`). Among Us was closed and
"Return to launcher after a game" was on.

| Launched from | main | this branch |
|---|---|---|
| Calculator (stands in for a non-Home frontend) | Android home |
Calculator |
| Home | Android home | Android home |
| DroidDeck's Games tab | DroidDeck | DroidDeck |

## Credits
Reported on Discord by whatsupbros.
2026-10-23 20:45:32 -04:00
maxjivi05 4a57c6f6f1 chore: drop the comments this change added 2026-10-23 20:45:14 -04:00
maxjivi05 2d9d4dbeb0 Merge branch 'main' into fix/steam-client-download
# Conflicts:
#	tools/linuxfs/overlay/usr/local/bin/droiddeck-steam-install
#	tools/tests/test_steam_install.py
2026-10-23 20:23:44 -04:00
MaxsTechReview 866551e797 fix: Snapdragon 8 Gen 2 no longer pins Steam to one core by default (#1441)
## Summary

Since 0.5.0, Snapdragon 8 Gen 2 devices (Retroid Pocket 6, Galaxy S23,
AYN Thor) pin the Steam client, its UI helper and gamescope to the
single prime core whenever the core settings were never touched. The
Steam menu and overlay lag on those devices, and games launched from
Steam get CPU-starved.

This drops that default, so 8 Gen 2 behaves like 0.4.0 and every other
chip: Android schedules Steam on all cores. Core choices users saved in
Performance are kept, and the all-core restore for games launched from a
pinned Steam client stays.

## Evidence

The device reports attached to both bug reports show the default in
effect:

| Device | SoC | Client core override | Client cores |
|---|---|---|---|
| Retroid Pocket 6 | QCS8550 | true (never set) | 7 |
| Galaxy S23 | SM8550 | true (never set) | 7 |

Both reporters say 0.4.0, which left Steam on all 8 cores, was smooth.
The PR that added the default did not benchmark it.

Tablet bench (REDMAGIC, SM8850): the 8 Gen 2 default was reproduced by
pinning Steam to one prime core (7) and games to cores 0-3. The test
scrolls the Big Picture library with the d-pad for 20 s and records
frame pacing. Two runs each:

| Steam client | UI fps | 1% low | p99 frame | off-cadence |
|---|---|---|---|---|
| all cores (this PR) | 114.4 / 115.2 | **62.5 / 62.5** | 16 ms | 4.7 /
4.0 % |
| one core (old default) | 109.7 / 110.9 | 41.7 / 41.7 | 24 ms | 8.0 /
7.0 % |

Among Us ran the same either way (58.9 vs 59.0 fps).

## Tests

`CoreAllocationPrefsTest`: absent preferences leave every core to the
scheduler, and saved choices are kept.

## Credits

- shanume (RP6) and Kacper (S23): reports, and the 8-cores-vs-1 finding.
- Kurt Himebauch (#654): the core allocation work this keeps, apart from
the default.
2026-10-23 20:22:23 -04:00
maxjivi05 a0c6545e77 fix: a link that joins DroidDeck's open task still returns to the caller 2026-10-23 20:22:05 -04:00
maxjivi05 c7bcd82782 fix: Snapdragon 8 Gen 2 no longer pins Steam to one core by default 2026-10-23 19:47:41 -04:00
maxjivi05 caaf6b3a01 fix: keep the link task id when an in-app resume reaches the session 2026-10-23 19:47:32 -04:00
superboo07 8123d5b361 xbox backend x86 to arm cross compilation 2026-10-23 23:40:49 +00:00
Kurt Himebauch 2b4bba63c5 docs: add the Trendshift #1 daily and weekly badges to the README (#1435) 2026-10-23 19:18:00 -04:00
maxjivi05 69b2b8fcdf fix: only close the game-link task that started the session 2026-10-23 19:17:08 -04:00
MaxsTechReview 0d8b5a7cf2 fix: stored components can be deleted after a Proton update (#1434)
After a Proton update, stored DXVK / VKD3D / FEX packages can't be
deleted. Components says they're "in use" by a Proton that's gone
(`DroidDeck-Proton_11-9.1` after updating to 11-11.1) or by a bare
number (`4005446849`).

## Cause
`deletePackage` and the Storage page's in-use check count every recorded
selection:
- **Removed Protons:** swaps on Protons that are no longer installed.
- **Out-of-date swaps:** swaps from before the Proton's version changed.
The launcher already ignores these.
- **Game profiles:** a per-game pick blocked the delete with the "swap
that Proton" message, naming the game's id.

## Fix
- **Out-of-date selections:** a selection only counts while its Proton
is installed and at the version the swap was made on. That's the rule
launches already use. Deleting a package removes its stale entries.
- **Profile picks:** deleting a package also clears it from any game's
component profile, so those games go back to the Proton's own copy.
Storage cleanup still keeps profile picks.
- **Live swaps:** a package swapped into an installed Proton is still
blocked. The message now shows the Proton's name rather than its id.

No new strings.

## Testing
On a REDMAGIC NP06J, with the state from the reports recreated:

| Case | main | this branch |
|---|---|---|
| DXVK swapped into a removed `DroidDeck-Proton_11-9.1` | Deleting
failed: in use in DroidDeck-Proton_11-9.1 | Deleted, stale entry removed
|
| FEX picked in game profile `4005446849` | Deleting failed: in use in
4005446849 | Deleted, profile cleared |
| DXVK swapped into installed Proton Experimental | blocked | blocked:
in use in Proton Experimental (ARM64) |

<img
src="https://raw.githubusercontent.com/maxjivi05/DroidDeck/pr-media/1434/main-stale-proton.jpg"
width="420"> <img
src="https://raw.githubusercontent.com/maxjivi05/DroidDeck/pr-media/1434/main-game-profile.jpg"
width="420">
<img
src="https://raw.githubusercontent.com/maxjivi05/DroidDeck/pr-media/1434/fix-game-profile.jpg"
width="420"> <img
src="https://raw.githubusercontent.com/maxjivi05/DroidDeck/pr-media/1434/fix-live-blocked.jpg"
width="420">

`ComponentsSelectionTest` covers removed, out-of-date and live
selections.

## Credits
Reported on Discord by Siigonis, Bado and woodrow1712.
2026-10-23 19:13:29 -04:00
maxjivi05 7261b26264 fix: a game started from another launcher returns to that launcher 2026-10-23 18:56:44 -04:00
maxjivi05 db9aae7b87 fix: delete the package before saving, and match Protons the same way 2026-10-23 18:56:24 -04:00
maxjivi05 70b8ec5de4 docs: add the Trendshift #1 daily and weekly badges to the README 2026-10-23 18:36:24 -04:00
maxjivi05 94b530ecb2 fix: stored components can be deleted after a Proton update 2026-10-23 18:28:35 -04:00
MaxsTechReview 906e0d1f7d fix: other apps can record game audio (#1430)
Fixes #1314.

Screen recorders and apps that use `AudioPlaybackCapture`
(MediaProjection) get silence from DroidDeck. The app targets SDK 28,
and Android blocks playback capture for apps below SDK 29 unless they
opt in. That was a side effect of the target SDK, not a choice.
`android:allowAudioPlaybackCapture="true"` opts in. Game audio already
plays with `AAUDIO_USAGE_GAME`, a usage that capture allows.

REDMAGIC NP06J with Among Us running, `dumpsys media.audio_policy`
("Allow playback capture log"); the game's streams are AAudio
`USAGE_GAME` with no capture-blocking flags:

| Build | |
| --- | --- |
| main | `uid=10494, allowPlaybackCapture=false,
packageName=com.droiddeck.launcher` |
| this PR | `uid=10494, allowPlaybackCapture=true,
packageName=com.droiddeck.launcher` |

## Credits
Requested and diagnosed by @WilsonNet in #1314.
2026-10-23 18:01:24 -04:00
maxjivi05 992912fdf8 fix: other apps can record game audio 2026-10-23 17:43:44 -04:00
MaxsTechReview 4ff4be2371 fix: keep a slightly early vsync tick for frame pacing (#1405)
Gamescope paces from the presentation timestamp. The Choreographer tick
is often still slightly ahead of the render thread, and that tick was
thrown away, so the draw time was reported instead.

A tick within one refresh of the draw is now kept, whether it is
slightly ahead or slightly behind. A missing tick, or one more than a
refresh away, still falls back to the draw time.
2026-10-23 17:00:32 -04:00