""" Android Lights API — LightsManager, Light, LightState, LightSession, LightsRequest 方法签名完全对齐 Android SDK """ from __future__ import annotations import os import sys import time import uuid import threading from typing import Any, Dict, List, Optional, Set, Tuple, Callable from enum import IntEnum from .._core import Stub, AndroidOnlyError from ..java.lang import RuntimeException IllegalArgumentException = type("IllegalArgumentException", (RuntimeException,), {}) # ═══════════════════════════════════════════════════════════════ # 常量 # ═══════════════════════════════════════════════════════════════ # LIGHT_ID_* 常量 LIGHT_ID_BACKLIGHT = 0 LIGHT_ID_KEYBOARD = 1 LIGHT_ID_BUTTONS = 2 LIGHT_ID_BATTERY = 3 LIGHT_ID_NOTIFICATIONS = 4 LIGHT_ID_ATTENTION = 5 LIGHT_ID_BLUETOOTH = 6 LIGHT_ID_WIFI = 7 LIGHT_ID_MICROPHONE = 8 LIGHT_ID_CAMERA = 9 LIGHT_ID_COUNT = 10 LIGHT_ID_MICROPHONE_MUTE = 11 LIGHT_ID_CAMERA_MUTE = 12 LIGHT_ID_POWER = 13 LIGHT_ID_ADAPTIVE_BACKLIGHT = 14 LIGHT_ID_CHARGING = 15 LIGHT_ID_ERROR = 16 LIGHT_ID_MANUAL_BACKLIGHT = 17 LIGHT_ID_MAX = 31 # BRIGHTNESS_* 常量 BRIGHTNESS_MIN = 0 BRIGHTNESS_LOW = 25 BRIGHTNESS_MEDIUM = 127 BRIGHTNESS_HIGH = 200 BRIGHTNESS_MAX = 255 BRIGHTNESS_OFF = 0 BRIGHTNESS_FULL = 255 BRIGHTNESS_DEFAULT = 127 # LIGHT_TYPE_* 常量 LIGHT_TYPE_MANUAL = 0 LIGHT_TYPE_AUTOMATIC = 1 LIGHT_TYPE_MICROPHONE = 2 LIGHT_TYPE_CAMERA = 3 LIGHT_TYPE_NOTIFICATION = 4 LIGHT_TYPE_ATTENTION = 5 LIGHT_TYPE_RGB = 6 LIGHT_TYPE_MONOCHROME = 7 LIGHT_TYPE_POWER = 8 LIGHT_TYPE_BATTERY = 9 LIGHT_TYPE_ADAPTIVE = 10 LIGHT_TYPE_BLINKING = 11 # LIGHT_CAPABILITY 常量 LIGHT_CAPABILITY_NONE = 0 LIGHT_CAPABILITY_BRIGHTNESS = 1 LIGHT_CAPABILITY_RGB = 2 LIGHT_CAPABILITY_COLOR_TEMPERATURE = 4 LIGHT_CAPABILITY_BLINKING = 8 LIGHT_CAPABILITY_DIMMABLE = 16 LIGHT_CAPABILITY_ADAPTIVE = 32 LIGHT_CAPABILITY_MICROPHONE = 64 LIGHT_CAPABILITY_CAMERA = 128 # FLASH_MODE 常量 FLASH_MODE_NONE = 0 FLASH_MODE_HARDWARE = 1 FLASH_MODE_SOFTWARE = 2 FLASH_MODE_TIMED = 3 FLASH_MODE_INFINITE = 4 # LIGHT_STATE 常量 LIGHT_STATE_ON = 1 LIGHT_STATE_OFF = 0 LIGHT_STATE_BLINKING = 2 LIGHT_STATE_BREATHING = 3 LIGHT_STATE_PULSING = 4 # ═══════════════════════════════════════════════════════════════ # LightState # ═══════════════════════════════════════════════════════════════ class LightState(Stub): """LightState — 灯光状态""" def __init__(self): super().__init__() self._color = 0 self._brightness = 0 self._brightness_mode = LIGHT_TYPE_MANUAL self._flash_mode = FLASH_MODE_NONE self._flash_on_ms = 0 self._flash_off_ms = 0 self._state = LIGHT_STATE_OFF self._rgb_color = (0, 0, 0) self._color_temperature = 6500 self._is_hardware = False self._pulse_duration = 0 self._breathing_enabled = False self._fade_in_time = 0 self._fade_out_time = 0 self._brightness_float = 0.0 self._brightness_nits = 0.0 def getColor(self) -> int: return self._color def setColor(self, color: int) -> None: self._color = color self._rgb_color = ((color >> 16) & 0xFF, (color >> 8) & 0xFF, color & 0xFF) def getBrightness(self) -> int: return self._brightness def setBrightness(self, brightness: int) -> None: self._brightness = max(0, min(255, brightness)) self._brightness_float = self._brightness / 255.0 def getBrightnessMode(self) -> int: return self._brightness_mode def setBrightnessMode(self, mode: int) -> None: self._brightness_mode = mode def getFlashMode(self) -> int: return self._flash_mode def setFlashMode(self, mode: int) -> None: self._flash_mode = mode def getFlashOnMs(self) -> int: return self._flash_on_ms def setFlashOnMs(self, onMs: int) -> None: self._flash_on_ms = onMs def getFlashOffMs(self) -> int: return self._flash_off_ms def setFlashOffMs(self, offMs: int) -> None: self._flash_off_ms = offMs def getState(self) -> int: return self._state def setState(self, state: int) -> None: self._state = state def isOn(self) -> bool: return self._state != LIGHT_STATE_OFF def getRgbColor(self) -> Tuple[int, int, int]: return self._rgb_color def setRgbColor(self, r: int, g: int, b: int) -> None: self._rgb_color = (r & 0xFF, g & 0xFF, b & 0xFF) self._color = (r << 16) | (g << 8) | b def getColorTemperature(self) -> int: return self._color_temperature def setColorTemperature(self, temperature: int) -> None: self._color_temperature = max(1000, min(20000, temperature)) def isHardwareControlled(self) -> bool: return self._is_hardware def setFadeInTime(self, ms: int) -> None: self._fade_in_time = ms def setFadeOutTime(self, ms: int) -> None: self._fade_out_time = ms def getBrightnessFloat(self) -> float: return self._brightness_float def getBrightnessNits(self) -> float: return self._brightness_nits def setBrightnessNits(self, nits: float) -> None: self._brightness_nits = nits def equals(self, other: Any) -> bool: if isinstance(other, LightState): return (self._color == other._color and self._brightness == other._brightness) return False def hashCode(self) -> int: return hash((self._color, self._brightness)) & 0x7FFFFFFF def toString(self) -> str: return ( f"LightState(color=0x{self._color:06x}, " f"brightness={self._brightness}, " f"state={self._state})" ) # ═══════════════════════════════════════════════════════════════ # Light # ═══════════════════════════════════════════════════════════════ class Light(Stub): """Light — 灯光设备""" LIGHT_TYPE_MANUAL = LIGHT_TYPE_MANUAL LIGHT_TYPE_AUTOMATIC = LIGHT_TYPE_AUTOMATIC LIGHT_TYPE_MICROPHONE = LIGHT_TYPE_MICROPHONE LIGHT_TYPE_CAMERA = LIGHT_TYPE_CAMERA LIGHT_TYPE_NOTIFICATION = LIGHT_TYPE_NOTIFICATION LIGHT_TYPE_ATTENTION = LIGHT_TYPE_ATTENTION LIGHT_TYPE_RGB = LIGHT_TYPE_RGB LIGHT_TYPE_ADAPTIVE = LIGHT_TYPE_ADAPTIVE LIGHT_TYPE_BLINKING = LIGHT_TYPE_BLINKING def __init__(self, light_id: int = 0, light_type: int = LIGHT_TYPE_MANUAL): super().__init__() self._id = light_id self._type = light_type self._ordinal = light_id self._capabilities = LIGHT_CAPABILITY_BRIGHTNESS self._name: Optional[str] = None self._is_available = True self._default_brightness = BRIGHTNESS_DEFAULT self._max_brightness = BRIGHTNESS_MAX self._min_brightness = BRIGHTNESS_MIN self._supports_rgb = False self._supports_color_temperature = False self._supports_blinking = False self._supports_dimming = True self._supports_adaptive = False self._default_color = 0xFFFFFF self._default_color_temperature = 6500 self._blink_supported = False self._pulse_supported = False self._breathing_supported = False self._fade_supported = False self._current_state = LightState() self._rgb_support = light_type == LIGHT_TYPE_RGB self._adaptive_support = light_type == LIGHT_TYPE_ADAPTIVE self._blink_support = light_type == LIGHT_TYPE_BLINKING def getId(self) -> int: return self._id def getType(self) -> int: return self._type def getOrdinal(self) -> int: return self._ordinal def getCapabilities(self) -> int: return self._capabilities def setCapabilities(self, caps: int) -> None: self._capabilities = caps def getName(self) -> Optional[str]: return self._name def setName(self, name: str) -> None: self._name = name def isAvailable(self) -> bool: return self._is_available def setAvailable(self, available: bool) -> None: self._is_available = available def getDefaultBrightness(self) -> int: return self._default_brightness def getMaxBrightness(self) -> int: return self._max_brightness def getMinBrightness(self) -> int: return self._min_brightness def supportsRgb(self) -> bool: return self._supports_rgb def supportsColorTemperature(self) -> bool: return self._supports_color_temperature def supportsBlinking(self) -> bool: return self._supports_blinking def supportsDimming(self) -> bool: return self._supports_dimming def supportsAdaptive(self) -> bool: return self._supports_adaptive def getDefaultColor(self) -> int: return self._default_color def getDefaultColorTemperature(self) -> int: return self._default_color_temperature def getCurrentState(self) -> LightState: return self._current_state def setCurrentState(self, state: LightState) -> None: self._current_state = state def canSetBrightness(self) -> bool: return self._capabilities & LIGHT_CAPABILITY_BRIGHTNESS != 0 def canSetColor(self) -> bool: return self._capabilities & LIGHT_CAPABILITY_RGB != 0 def canSetColorTemperature(self) -> bool: return self._capabilities & LIGHT_CAPABILITY_COLOR_TEMPERATURE != 0 def canBlink(self) -> bool: return self._capabilities & LIGHT_CAPABILITY_BLINKING != 0 def isDimmable(self) -> bool: return self._capabilities & LIGHT_CAPABILITY_DIMMABLE != 0 def isAdaptive(self) -> bool: return self._capabilities & LIGHT_CAPABILITY_ADAPTIVE != 0 def equals(self, other: Any) -> bool: if isinstance(other, Light): return self._id == other._id return False def hashCode(self) -> int: return self._id & 0x7FFFFFFF def toString(self) -> str: return f"Light(id={self._id}, type={self._type}, name={self._name})" # ═══════════════════════════════════════════════════════════════ # LightSession # ═══════════════════════════════════════════════════════════════ class LightSession(Stub): """LightSession — 灯光会话""" def __init__(self, light_id: int): super().__init__() self._session_id = str(uuid.uuid4()) self._light_id = light_id self._state = LightState() self._is_active = False self._created_at = time.time() self._last_update = time.time() self._priority = 0 self._owner: Optional[str] = None self._transient = False self._timeout_ms = 0 self._fade_duration_ms = 0 def getSessionId(self) -> str: return self._session_id def getLightId(self) -> int: return self._light_id def getState(self) -> LightState: return self._state def setState(self, state: LightState) -> None: self._state = state self._last_update = time.time() def isActive(self) -> bool: return self._is_active def setActive(self, active: bool) -> None: self._is_active = active def getCreatedAt(self) -> float: return self._created_at def getLastUpdate(self) -> float: return self._last_update def getPriority(self) -> int: return self._priority def setPriority(self, priority: int) -> None: self._priority = priority def getOwner(self) -> Optional[str]: return self._owner def setOwner(self, owner: str) -> None: self._owner = owner def isTransient(self) -> bool: return self._transient def setTransient(self, transient: bool) -> None: self._transient = transient def getTimeoutMs(self) -> int: return self._timeout_ms def setTimeoutMs(self, timeoutMs: int) -> None: self._timeout_ms = timeoutMs def getFadeDurationMs(self) -> int: return self._fade_duration_ms def setFadeDurationMs(self, ms: int) -> None: self._fade_duration_ms = ms def toString(self) -> str: return ( f"LightSession(id={self._session_id[:8]}..., " f"light={self._light_id}, " f"active={self._is_active})" ) # ═══════════════════════════════════════════════════════════════ # LightsRequest # ═══════════════════════════════════════════════════════════════ class LightsRequest(Stub): """LightsRequest — 灯光请求""" def __init__(self): super().__init__() self._light_states: Dict[int, LightState] = {} self._light_sessions: List[LightSession] = [] self._request_id = str(uuid.uuid4()) self._created_at = time.time() self._priority = 0 self._is_urgent = False self._callback: Optional[Callable] = None self._completed = False def addLightState(self, light_id: int, state: LightState) -> "LightsRequest": self._light_states[light_id] = state return self def addLightSession(self, session: LightSession) -> "LightsRequest": self._light_sessions.append(session) return self def removeLightState(self, light_id: int) -> None: self._light_states.pop(light_id, None) def getLightStates(self) -> Dict[int, LightState]: return dict(self._light_states) def getLightSessions(self) -> List[LightSession]: return list(self._light_sessions) def getRequestId(self) -> str: return self._request_id def getPriority(self) -> int: return self._priority def setPriority(self, priority: int) -> None: self._priority = priority def isUrgent(self) -> bool: return self._is_urgent def setUrgent(self, urgent: bool) -> None: self._is_urgent = urgent def isCompleted(self) -> bool: return self._completed def setCompleted(self, completed: bool) -> None: self._completed = completed def getLightCount(self) -> int: return len(self._light_states) def toString(self) -> str: return ( f"LightsRequest(id={self._request_id[:8]}..., " f"lights={len(self._light_states)}, " f"sessions={len(self._light_sessions)})" ) # ═══════════════════════════════════════════════════════════════ # LightsManager # ═══════════════════════════════════════════════════════════════ class LightsManager(Stub): """LightsManager — 灯光管理器 (桌面存根)""" LIGHT_ID_BACKLIGHT = LIGHT_ID_BACKLIGHT LIGHT_ID_KEYBOARD = LIGHT_ID_KEYBOARD LIGHT_ID_BUTTONS = LIGHT_ID_BUTTONS LIGHT_ID_BATTERY = LIGHT_ID_BATTERY LIGHT_ID_NOTIFICATIONS = LIGHT_ID_NOTIFICATIONS LIGHT_ID_ATTENTION = LIGHT_ID_ATTENTION LIGHT_ID_BLUETOOTH = LIGHT_ID_BLUETOOTH LIGHT_ID_WIFI = LIGHT_ID_WIFI LIGHT_ID_MICROPHONE = LIGHT_ID_MICROPHONE LIGHT_ID_CAMERA = LIGHT_ID_CAMERA LIGHT_ID_MICROPHONE_MUTE = LIGHT_ID_MICROPHONE_MUTE LIGHT_ID_CAMERA_MUTE = LIGHT_ID_CAMERA_MUTE LIGHT_ID_POWER = LIGHT_ID_POWER LIGHT_ID_ADAPTIVE_BACKLIGHT = LIGHT_ID_ADAPTIVE_BACKLIGHT LIGHT_ID_CHARGING = LIGHT_ID_CHARGING BRIGHTNESS_MIN = BRIGHTNESS_MIN BRIGHTNESS_LOW = BRIGHTNESS_LOW BRIGHTNESS_MEDIUM = BRIGHTNESS_MEDIUM BRIGHTNESS_HIGH = BRIGHTNESS_HIGH BRIGHTNESS_MAX = BRIGHTNESS_MAX BRIGHTNESS_OFF = BRIGHTNESS_OFF BRIGHTNESS_FULL = BRIGHTNESS_FULL BRIGHTNESS_DEFAULT = BRIGHTNESS_DEFAULT LIGHT_TYPE_MANUAL = LIGHT_TYPE_MANUAL LIGHT_TYPE_AUTOMATIC = LIGHT_TYPE_AUTOMATIC LIGHT_TYPE_MICROPHONE = LIGHT_TYPE_MICROPHONE LIGHT_TYPE_CAMERA = LIGHT_TYPE_CAMERA LIGHT_TYPE_NOTIFICATION = LIGHT_TYPE_NOTIFICATION LIGHT_TYPE_ATTENTION = LIGHT_TYPE_ATTENTION LIGHT_TYPE_RGB = LIGHT_TYPE_RGB LIGHT_TYPE_ADAPTIVE = LIGHT_TYPE_ADAPTIVE LIGHT_TYPE_BLINKING = LIGHT_TYPE_BLINKING _instance: Optional["LightsManager"] = None def __init__(self, context: Any = None): super().__init__() self._context = context self._lock = threading.Lock() self._lights: Dict[int, Light] = {} self._sessions: Dict[str, LightSession] = {} self._active_requests: List[LightsRequest] = [] self._default_brightness = 127 self._max_brightness = 255 self._min_brightness = 0 self._lights_available = True self._initialize_default_lights() def _initialize_default_lights(self) -> None: default_lights = [ (LIGHT_ID_BACKLIGHT, "backlight", LIGHT_TYPE_AUTOMATIC), (LIGHT_ID_KEYBOARD, "keyboard", LIGHT_TYPE_MANUAL), (LIGHT_ID_BUTTONS, "buttons", LIGHT_TYPE_MANUAL), (LIGHT_ID_BATTERY, "battery", LIGHT_TYPE_BATTERY), (LIGHT_ID_NOTIFICATIONS, "notifications", LIGHT_TYPE_NOTIFICATION), (LIGHT_ID_ATTENTION, "attention", LIGHT_TYPE_ATTENTION), (LIGHT_ID_BLUETOOTH, "bluetooth", LIGHT_TYPE_MANUAL), (LIGHT_ID_WIFI, "wifi", LIGHT_TYPE_MANUAL), (LIGHT_ID_MICROPHONE, "microphone", LIGHT_TYPE_MICROPHONE), (LIGHT_ID_CAMERA, "camera", LIGHT_TYPE_CAMERA), (LIGHT_ID_MICROPHONE_MUTE, "microphone_mute", LIGHT_TYPE_MICROPHONE), (LIGHT_ID_CAMERA_MUTE, "camera_mute", LIGHT_TYPE_CAMERA), (LIGHT_ID_POWER, "power", LIGHT_TYPE_POWER), (LIGHT_ID_ADAPTIVE_BACKLIGHT, "adaptive_backlight", LIGHT_TYPE_ADAPTIVE), (LIGHT_ID_CHARGING, "charging", LIGHT_TYPE_BATTERY), ] for lid, name, ltype in default_lights: light = Light(lid, ltype) light.setName(name) self._lights[lid] = light def getLight(self, lightId: int) -> Optional[Light]: with self._lock: return self._lights.get(lightId) def getLights(self) -> List[Light]: with self._lock: return list(self._lights.values()) def openSession(self, lightId: int) -> LightSession: session = LightSession(lightId) with self._lock: self._sessions[session.getSessionId()] = session return session def closeSession(self, session: LightSession) -> None: with self._lock: sid = session.getSessionId() if sid in self._sessions: session.setActive(False) del self._sessions[sid] def setLightState(self, lightId: int, state: LightState) -> None: with self._lock: light = self._lights.get(lightId) if light: light.setCurrentState(state) def setLightStates(self, states: Dict[int, LightState]) -> None: with self._lock: for lid, state in states.items(): light = self._lights.get(lid) if light: light.setCurrentState(state) def submitRequest(self, request: LightsRequest) -> None: with self._lock: self._active_requests.append(request) for lid, state in request.getLightStates().items(): light = self._lights.get(lid) if light: light.setCurrentState(state) for session in request.getLightSessions(): session.setActive(True) self._sessions[session.getSessionId()] = session request.setCompleted(True) def getActiveRequests(self) -> List[LightsRequest]: with self._lock: return list(self._active_requests) def getActiveSessions(self, lightId: int) -> List[LightSession]: with self._lock: return [s for s in self._sessions.values() if s.getLightId() == lightId and s.isActive()] def getDefaultBrightness(self) -> int: return self._default_brightness def setDefaultBrightness(self, brightness: int) -> None: self._default_brightness = max(0, min(255, brightness)) def getMaxBrightness(self) -> int: return self._max_brightness def getMinBrightness(self) -> int: return self._min_brightness def isAvailable(self) -> bool: return self._lights_available def toString(self) -> str: with self._lock: return ( f"LightsManager(lights={len(self._lights)}, " f"sessions={len(self._sessions)}, " f"requests={len(self._active_requests)})" )