test(automotive): assert the picture-in-picture vetoes on every host

41ffaa7f2 gated picture-in-picture on FEATURE_AUTOMOTIVE and added a
settings case for it, but the assertion that case leads with — a stored
auto-PiP true surviving a read — needs supportsPictureInPicture() to be
true, and that gate ends in Platform.isAndroid || isIOS || isMacOS. The
term is false and unmockable on the Linux and Windows runners, so the
case passed on a macOS host and could never pass in CI: sanity checks
have been red for six commits on this one failure out of 4723. f13f5af6e
recorded it as a pre-existing Windows-host failure, but it entered in
this window and is red on Linux too.

Extract the gate's decision into a pure pictureInPictureAllowed that
takes the host's own capability as a parameter, the way
driver_distraction.dart already splits automotivePlaybackAllowed from its
ambient wrapper. The boolean algebra is unchanged, so the three callers
keep their behaviour; what changes is that the automotive and TV vetoes
become observable where every Platform branch is false, instead of being
vacuous on the host that gates the release.

The settings case keeps the pref-level contract on both host classes: a
stored true survives where the host supports PiP, and the gate pins it
off where it does not.

Verified with the host term forced false to emulate a Linux runner: both
files stay green, as does the full suite on macOS.
This commit is contained in:
edde746
2026-07-30 03:16:49 +02:00
parent 0a6865fa18
commit 88ffe0806d
3 changed files with 60 additions and 6 deletions
+25 -5
View File
@@ -48,6 +48,25 @@ AndroidTvFeatureDetection detectAndroidTvFromSystemFeatures(Iterable<String> fea
);
}
/// Whether a floating player may be offered, given the host platform's own
/// picture-in-picture capability and the detected form factor.
///
/// Cars commonly lack `FEATURE_PICTURE_IN_PICTURE`, and a floating player would
/// keep the app's UI on screen while driving, which `DD-2` forbids. TV form
/// factors have no windowed surface to float into.
///
/// [hostSupportsPictureInPicture] is injected rather than read from [Platform]
/// so the form-factor vetoes stay observable on hosts that never support PiP:
/// on the Linux and Windows CI runners every [Platform] branch of the real gate
/// is false and unmockable, which would otherwise make the vetoes vacuous
/// exactly where the release is gated.
bool pictureInPictureAllowed({
required bool hostSupportsPictureInPicture,
required bool isAppleTv,
required bool isTv,
required bool isAutomotive,
}) => hostSupportsPictureInPicture && !isAppleTv && !isTv && !isAutomotive;
/// Service for detecting if the app is running on Android TV or Apple TV.
class TvDetectionService {
static final AsyncSingleton<TvDetectionService> _singleton = AsyncSingleton();
@@ -267,11 +286,12 @@ class PlatformDetector {
return isAppleTV() || isDesktopOS() || (Platform.isAndroid && isTV());
}
static bool supportsPictureInPicture() {
// Cars commonly lack FEATURE_PICTURE_IN_PICTURE, and a floating player
// would keep the app's UI on screen while driving, which `DD-2` forbids.
return !isAppleTV() && !isTV() && !isAutomotive() && (Platform.isAndroid || Platform.isIOS || Platform.isMacOS);
}
static bool supportsPictureInPicture() => pictureInPictureAllowed(
hostSupportsPictureInPicture: Platform.isAndroid || Platform.isIOS || Platform.isMacOS,
isAppleTv: isAppleTV(),
isTv: isTV(),
isAutomotive: isAutomotive(),
);
/// Detects if the device is likely a tablet based on screen size
/// Uses diagonal screen size to determine if device is a tablet