iPhone FoldGate

This commit is contained in:
firestar5683
2026-09-09 15:32:38 -05:00
parent 50e2c21dbd
commit eedd73e522
54 changed files with 4210 additions and 216 deletions
@@ -0,0 +1,147 @@
from types import SimpleNamespace
from openpilot.selfdrive.ui import ui_state as ui_state_module
class FakeParams:
def __init__(self, **values):
self.values = values
def get_bool(self, key, **_kwargs):
return bool(self.values.get(key, False))
def get_int(self, key, **_kwargs):
return int(self.values.get(key, 0))
class PassthroughFilter:
def update(self, value):
return value
def make_device(monkeypatch, **overrides):
values = {
"ScreenManagement": True,
"ScreenBrightness": 35,
"ScreenBrightnessOnroad": 45,
"ScreenTimeout": 30,
"ScreenTimeoutOnroad": 10,
"StandbyMode": False,
}
values.update(overrides)
state = SimpleNamespace(
ui_params=FakeParams(**values),
status=ui_state_module.UIStatus.DISENGAGED,
started=False,
ignition=False,
light_sensor=-1.0,
sm={},
)
monkeypatch.setattr(ui_state_module, "ui_state", state)
monkeypatch.setattr(ui_state_module.gui_app, "big_ui", lambda: False)
monkeypatch.setattr(ui_state_module.gui_app, "_mouse_events", [])
device = ui_state_module.Device()
device._brightness_filter = PassthroughFilter()
return device, state
def test_manual_brightness_applies_to_current_device_state(monkeypatch):
device, state = make_device(monkeypatch)
assert device._calculate_brightness() == 35
state.started = True
assert device._calculate_brightness() == 45
def test_auto_brightness_preserves_existing_behavior(monkeypatch):
device, state = make_device(monkeypatch, ScreenBrightness=101, ScreenBrightnessOnroad=101)
assert device._calculate_brightness() == ui_state_module.BACKLIGHT_OFFROAD
state.started = True
state.light_sensor = -1.0
assert device._calculate_brightness() == ui_state_module.BACKLIGHT_OFFROAD
def test_screen_management_off_ignores_custom_values(monkeypatch):
device, state = make_device(monkeypatch, ScreenManagement=False, ScreenBrightness=10, ScreenBrightnessOnroad=20,
StandbyMode=True)
assert device._calculate_brightness() == ui_state_module.BACKLIGHT_OFFROAD
state.started = True
device._interaction_time = 0
assert device._calculate_brightness() == ui_state_module.BACKLIGHT_OFFROAD
assert device.interactive_timeout == 30
def test_screen_settings_refresh_after_external_param_change(monkeypatch):
now = 100.0
monkeypatch.setattr(ui_state_module.time, "monotonic", lambda: now)
device, state = make_device(monkeypatch)
state.started = True
state.ignition = True
device._ignition = True
device._interaction_time = now + 10
state.ui_params.values["ScreenBrightnessOnroad"] = 72
state.ui_params.values["ScreenTimeoutOnroad"] = 25
now += device.SCREEN_SETTINGS_REFRESH_INTERVAL
device._refresh_screen_settings()
assert device._calculate_brightness() == 72
assert device.interactive_timeout == 25
assert device._interaction_time == now + 25
def test_standby_blanks_after_timeout_and_touch_wakes(monkeypatch):
now = 100.0
monkeypatch.setattr(ui_state_module.time, "monotonic", lambda: now)
device, state = make_device(monkeypatch, StandbyMode=True)
state.started = True
state.ignition = True
device._ignition = True
device._interaction_time = now - 1
assert device._calculate_brightness() == 0
monkeypatch.setattr(ui_state_module.gui_app, "_mouse_events", [SimpleNamespace(left_down=True)])
device._update_wakefulness()
assert device._interaction_time == now + 10
assert device._calculate_brightness() == 45
def test_hide_ui_blanks_after_timeout_and_touch_wakes(monkeypatch):
now = 100.0
monkeypatch.setattr(ui_state_module.time, "monotonic", lambda: now)
device, state = make_device(monkeypatch, ScreenBrightnessOnroad=0)
state.started = True
state.ignition = True
device._ignition = True
device._interaction_time = now - 1
assert device._calculate_brightness() == 0
monkeypatch.setattr(ui_state_module.gui_app, "_mouse_events", [SimpleNamespace(left_down=True)])
device._update_wakefulness()
assert device._interaction_time == now + 10
assert device._calculate_brightness() == 5
def test_standby_wakes_for_visible_alert(monkeypatch):
now = 100.0
monkeypatch.setattr(ui_state_module.time, "monotonic", lambda: now)
device, state = make_device(monkeypatch, StandbyMode=True)
state.started = True
state.ignition = True
device._ignition = True
device._interaction_time = now - 1
device._visible_onroad_alert = lambda: True
device._update_wakefulness()
assert device._interaction_time == now + 10
assert device._calculate_brightness() == 45
+101 -10
View File
@@ -297,6 +297,8 @@ class UIState:
class Device:
SCREEN_SETTINGS_REFRESH_INTERVAL = 1.0
def __init__(self):
self._ignition = False
self._interaction_time: float = -1
@@ -306,6 +308,16 @@ class Device:
self._awake: bool = True
self._params = ui_state.ui_params
self._screen_settings_refresh_time: float = 0.0
self._screen_management = False
self._screen_brightness = 101
self._screen_brightness_onroad = 101
self._screen_timeout = 30
self._screen_timeout_onroad = 30
self._standby_mode = False
self._last_status = ui_state.status
self._refresh_screen_settings(force=True)
self._offroad_brightness: int = BACKLIGHT_OFFROAD
self._last_brightness: int = 0
self._brightness_filter = FirstOrderFilter(BACKLIGHT_OFFROAD, 10.00, 1 / gui_app.target_fps)
@@ -325,8 +337,8 @@ class Device:
if self._override_interactive_timeout is not None:
return self._override_interactive_timeout
timeout_onroad = self._params.get_int("ScreenTimeoutOnroad", return_default=True)
timeout_offroad = self._params.get_int("ScreenTimeout", return_default=True)
timeout_onroad = self._screen_timeout_onroad
timeout_offroad = self._screen_timeout
if timeout_onroad <= 0:
timeout_onroad = 10 if gui_app.big_ui() else 5
@@ -345,12 +357,54 @@ class Device:
self._interactive_timeout_callbacks.append(callback)
def update(self):
self._refresh_screen_settings()
# do initial reset
if self._interaction_time <= 0:
self._reset_interactive_timeout()
self._update_brightness()
self._update_wakefulness()
self._update_brightness()
def _refresh_screen_settings(self, force: bool = False) -> None:
now = time.monotonic()
if not force and now - self._screen_settings_refresh_time < self.SCREEN_SETTINGS_REFRESH_INTERVAL:
return
previous = (
self._screen_management,
self._screen_brightness,
self._screen_brightness_onroad,
self._screen_timeout,
self._screen_timeout_onroad,
self._standby_mode,
)
self._screen_management = self._params.get_bool("ScreenManagement")
if self._screen_management:
self._screen_brightness = min(max(self._params.get_int("ScreenBrightness", return_default=True), 0), 101)
self._screen_brightness_onroad = min(max(self._params.get_int("ScreenBrightnessOnroad", return_default=True), 0), 101)
self._screen_timeout = self._params.get_int("ScreenTimeout", return_default=True)
self._screen_timeout_onroad = self._params.get_int("ScreenTimeoutOnroad", return_default=True)
self._standby_mode = self._params.get_bool("StandbyMode")
else:
self._screen_brightness = 101
self._screen_brightness_onroad = 101
self._screen_timeout = 30
self._screen_timeout_onroad = 30
self._standby_mode = False
self._screen_settings_refresh_time = now
current = (
self._screen_management,
self._screen_brightness,
self._screen_brightness_onroad,
self._screen_timeout,
self._screen_timeout_onroad,
self._standby_mode,
)
if previous != current and self._interaction_time > 0:
self._reset_interactive_timeout()
def set_offroad_brightness(self, brightness: int | None):
if brightness is None:
@@ -358,6 +412,15 @@ class Device:
self._offroad_brightness = min(max(brightness, 0), 100)
def _update_brightness(self):
brightness = self._calculate_brightness()
if brightness != self._last_brightness:
if self._brightness_thread is None or not self._brightness_thread.is_alive():
self._brightness_thread = threading.Thread(target=HARDWARE.set_screen_brightness, args=(brightness,))
self._brightness_thread.start()
self._last_brightness = brightness
def _calculate_brightness(self) -> int:
clipped_brightness = self._offroad_brightness
if ui_state.started and ui_state.light_sensor >= 0:
@@ -374,19 +437,26 @@ class Device:
brightness = round(self._brightness_filter.update(clipped_brightness))
if not self._awake:
brightness = 0
elif ui_state.started and self._standby_mode and time.monotonic() > self._interaction_time:
brightness = 0
elif ui_state.started and self._screen_brightness_onroad != 101:
brightness = max(5, self._screen_brightness_onroad) if time.monotonic() <= self._interaction_time else self._screen_brightness_onroad
elif not ui_state.started and self._screen_brightness != 101:
brightness = self._screen_brightness
if brightness != self._last_brightness:
if self._brightness_thread is None or not self._brightness_thread.is_alive():
self._brightness_thread = threading.Thread(target=HARDWARE.set_screen_brightness, args=(brightness,))
self._brightness_thread.start()
self._last_brightness = brightness
return brightness
def _update_wakefulness(self):
# Handle interactive timeout
ignition_just_turned_off = not ui_state.ignition and self._ignition
ignition_state_changed = ui_state.ignition != self._ignition
self._ignition = ui_state.ignition
if ignition_just_turned_off or any(ev.left_down for ev in gui_app.mouse_events):
status_changed = ui_state.status != self._last_status and ui_state.status != UIStatus.OVERRIDE
self._last_status = ui_state.status
wake_for_onroad_event = (ui_state.started and self._standby_mode and self._screen_brightness_onroad != 0 and
(status_changed or self._visible_onroad_alert()))
if ignition_state_changed or any(ev.left_down for ev in gui_app.mouse_events) or wake_for_onroad_event:
self._reset_interactive_timeout()
interaction_timeout = time.monotonic() > self._interaction_time
@@ -397,6 +467,27 @@ class Device:
self._set_awake(ui_state.ignition or not interaction_timeout or PC)
@staticmethod
def _visible_onroad_alert() -> bool:
if not ui_state.started:
return False
sm = ui_state.sm
try:
selfdrive_state = sm["selfdriveState"]
if selfdrive_state.alertSize != log.SelfdriveState.AlertSize.none:
return True
if selfdrive_state.alertStatus != log.SelfdriveState.AlertStatus.normal:
return True
except Exception:
pass
try:
starpilot_state = sm["starpilotSelfdriveState"]
return getattr(starpilot_state.alertSize, "raw", 0) != 0
except Exception:
return False
def _set_awake(self, on: bool):
if on != self._awake:
self._awake = on