1
0
Fork 0

Move AndroidTvOpiOverlay to product to disable UI width cap

The config_maxUiWidth=0 override never took effect from /vendor/overlay:
static RRO precedence is decided by partition order before priority, so
the product-partition TvFrameworkOverlay (1920) always won and silently
re-capped the UI to 1920x1080 on 4K displays. Moving our overlay to the
product partition lets its priority 10 beat TvFrameworkOverlay's 0, so
the cap is disabled and the UI renders at the display's native
resolution. Users can select a lower mode in Settings if needed.
This commit is contained in:
Brendan Szymanski 2026-07-16 13:29:27 -04:00
parent c7a7dc3593
commit 04e94e9938
3 changed files with 31 additions and 11 deletions

View file

@ -3,9 +3,15 @@
// //
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
// This overlay MUST live on the product partition: it overrides resources that
// TvFrameworkOverlay (a product-partition RRO from device/google/atv) also
// overrides, and static RRO precedence is decided by partition order first
// (system < vendor < odm < oem < product < system_ext) and android:priority
// second. From /vendor/overlay our entries always lose to TvFrameworkOverlay
// regardless of priority; on /product our priority 10 beats its priority 0.
runtime_resource_overlay { runtime_resource_overlay {
name: "AndroidTvOpiOverlay", name: "AndroidTvOpiOverlay",
resource_dirs: ["res"], resource_dirs: ["res"],
sdk_version: "current", sdk_version: "current",
vendor: true, product_specific: true,
} }

View file

@ -16,9 +16,23 @@
--> -->
<resources> <resources>
<!-- Override TvFrameworkOverlay's config_maxUiWidth value in the values-xhdpi <!-- Disable TvFrameworkOverlay's config_maxUiWidth cap so the UI renders at
bucket, which this device now resolves via PRODUCT_AAPT_PREF_CONFIG=xhdpi the display's native resolution (e.g. true 4K UI on a 4K TV); the user
(matching the RPi5 ATV approach). Our RRO priority 10 beats their priority can drop to a lower mode in Settings -> Display & Sound -> Resolution if
0, so 0 (disabled cap) wins. --> performance demands it.
Why this exact shape is required (all verified on hardware 2026-07-16):
- PRODUCT_AAPT_PREF_CONFIG strips all other density buckets from every
overlay APK at build time, so both TvFrameworkOverlay and this overlay
ship only their values/ and values-xhdpi entries. Adding more buckets
here is pointless; this bucket (plus values/) is the whole contest.
- The runtime density (ro.sf.lcd_density=240) always resolves the xhdpi
bucket, so this entry is the one that wins or loses.
- Both overlays define the same bucket, so config specificity ties and
precedence decides — which is partition order FIRST, android:priority
second. This overlay must therefore be product_specific (see
Android.bp); from /vendor it always loses to the product-partition
TvFrameworkOverlay (1920) no matter the priority, which silently
re-caps the UI to 1920x1080 on 4K displays. -->
<integer name="config_maxUiWidth">0</integer> <integer name="config_maxUiWidth">0</integer>
</resources> </resources>

View file

@ -51,12 +51,12 @@
<!-- Maximum width, in pixels, to restrain the UI layer-stack to; height and <!-- Maximum width, in pixels, to restrain the UI layer-stack to; height and
density are scaled to match, then SurfaceFlinger upscales to the panel. density are scaled to match, then SurfaceFlinger upscales to the panel.
The stock Android TV framework overlay (TvFrameworkOverlay) sets this to The stock Android TV framework overlay (TvFrameworkOverlay) sets this to
1280 in its values-tvdpi bucket, which this device resolves. That caps a 1920 (values/ and values-xhdpi buckets survive PRODUCT_AAPT_PREF_CONFIG
native 1920x1080 panel to a 1280x720 @ 320dpi logical display, making the stripping), which scales a 4K display down to a 1920x1080 logical UI.
whole UI render oversized (SurfaceFlinger scales 720p -> 1080p) and making 0 disables the cap so the UI renders at the display's native resolution.
the Settings "Resolution" picker a no-op (the layer stack is capped The density-qualified values-xhdpi entry (see values-xhdpi/config.xml) is
regardless of the scanout mode). 0 disables the cap so the UI renders at the one that actually decides the contest at runtime; this unqualified
the panel's native resolution. --> entry is kept as a fallback for density configs with no xhdpi match. -->
<integer name="config_maxUiWidth">0</integer> <integer name="config_maxUiWidth">0</integer>
</resources> </resources>