Merge remote-tracking branch 'origin/main' into fm/tv-focus-style
All checks were successful
review/code-gpt Firstmate read the PR evidence and viewed the before/after pairs and native captures against the approved card ring (4 px straddle, no gap); measured ring bounds, inventory with unchanged fill surfaces listed; 20+ targeted native captures and key/session tests; device verification follows on the optimized build
review/design-claude Firstmate read the PR evidence and viewed the before/after pairs and native captures against the approved card ring (4 px straddle, no gap); measured ring bounds, inventory with unchanged fill surfaces listed; 20+ targeted native captures and key/session tests; device verification follows on the optimized build

This commit is contained in:
justinzeus 2026-11-06 15:52:02 +01:00
commit 33dc65bf18
5 changed files with 113 additions and 0 deletions

View file

@ -27,6 +27,84 @@ Upstream enables JVM unit tests only for debug variants; there is no
`testDefaultReleaseUnitTest` task. `make test` uses the closest default-flavor
task without changing upstream's test configuration.
## Optimized side-by-side comparison
The `optimized` build type inherits `release`: R8 optimization/minification,
resource shrinking, non-debuggable code, dependency consumer keep rules and
dependency baseline profiles. It changes only signing (the Android debug key),
package (`org.justinvisser.wolfskin.tv.opt`) and launcher label (`Wolfskin (Opt)`).
The launcher icon/banner and release-compatible version name are unchanged:
the shared upgrade/updater parser rejects extra suffixes such as `-opt`.
`make apk` remains the clean, release-key-signed production build; neither its
signing flow nor the existing debug build changes.
Build all four default-flavor outputs in one invocation through the container
wrapper, without a release keystore. On a host whose Gradle cache already holds
the pinned native extensions and their metadata:
```sh
bash docker/gradle.sh optimized --offline \
-PWholphinExtensionsUsername=JustinZeus \
-PWholphinExtensionsPassword=unused \
:app:assembleDefaultOptimized
```
The unused password is not a credential: offline resolution never contacts
GitHub Packages. A cold cache instead needs a read-packages credential supplied
through the existing `ORG_GRADLE_PROJECT_WholphinExtensionsUsername` and
`ORG_GRADLE_PROJECT_WholphinExtensionsPassword` hooks inside the build container,
or securely seeded cached artifacts. No release signing inputs are needed.
Without native extension configuration, the existing dependency selection uses
the MPV stub and omits ffmpeg/AV1, just like `make apk-debug`; that is not a
playback-complete comparison. Inspect native libraries before installing.
Outputs are in `app/build/outputs/apk/default/optimized/`: universal, arm64-v8a,
armeabi-v7a and x86_64. Keep
`app/build/outputs/mapping/defaultOptimized/mapping.txt` with those APKs to
deobfuscate crashes. This variant shares release library variants and the release
`debugHomeSnapshot` implementation, not `src/debug` or its preview JSON/artwork.
`BuildConfig.DEBUG` remains false: no preview-fixture setting, debug StrictMode
or Compose diagnostic stack traces.
This is a fresh app sandbox: sign in with Jellyfin Quick Connect or the normal
server/user flow again; it does not inherit the debug/release app's logins or
preferences. **Wolfskin screens** defaults on, and the same Advanced switch can
restore upstream screens. The same Conductarr door
(`https://wolfskin-tv.justinvisser.org`) and URL override apply. The selected
Jellyfin user's token is borrowed for Conductarr; no app-specific TV credential
or embedded secret is added. All other settings retain release behavior,
including update checks; a production release APK is not an update for this
separate package/debug signer.
`androidx.profileinstaller` and library-provided profiles already exist. There
is no recorded app baseline-profile source or Macrobenchmark module.
`src/optimized/baselineProfiles/baseline-prof.txt` adds a hand-maintained seed: application and
activity classes plus their `onCreate` methods, `WolfskinAppKt`,
`WolfskinScreenPreference` and `ConductarrPreference`. AGP merges it with library
profiles, rewrites it through R8 and packages `assets/dexopt/baseline.prof` and
`baseline.profm`. It is not a measured navigation profile or evidence of a speedup.
To replace the seed, add an AndroidX Baseline Profile producer/Macrobenchmark
module, record cold launch, Quick Connect/sign-in, person selection, Home,
Libraries, Discover, title pages and playback on a suitable device, then rebuild
and compare startup/frame timings. Device-driven recording and runtime checks
remain separate from an APK build.
The optimized source set explicitly registers that profile directory; a bare
`src/optimized/baseline-prof.txt` is not consumed by this AGP configuration.
Static verification: use `aapt2 dump badging` for package/label/SDKs and absence
of `application-debuggable`; `apksigner verify --print-certs` for the debug
signer; `unzip -l` for both dexopt assets, native ABI contents and absence of
`assets/wolfskin-*`/`assets/library/` fixtures. Review R8 warnings and effective
consumer rules rather than adding blanket keeps. JVM tests do not prove
minified Hilt/Room/serialization/JNI runtime safety; exercise sign-in, real
Conductarr reads, artwork, database reopen and each player on the comparison box.
`help --task :app:testDefaultOptimizedUnitTest` confirms that this non-debug
variant has no JVM unit-test task, just like release. The existing debug JVM
`VersionCompareTests` receives the actual optimized version name from the variant
API and checks it with the same `Version.fromString` used by upgrade/update handling.
Build logic is otherwise checked through actual APK assembly and static inspection.
## Upstream v1.1.0 integration
The release merge brings Kotlin `2.4.21`, Gradle `9.8.2`, AGP `9.5.0`, and