新增模块覆盖: 系统层 (14): system, security, print, opengl, renderscript, transition, test, service_notification, service_controls, service_quicksettings, service_wallpaper, service_autofill, service_dreams, service_vr 应用层 (13): app_admin, app_backup, app_job, app_usage, app_role, app_people, appwidget, companion, credentials, mtp, sip, telecom, speech 硬件媒体层 (15): hardware_display, hardware_fingerprint, hardware_usb, hardware_input, media_audiofx, media_browse, media_session, media_tv, media_midi, media_projection, uwb, se, view_autofill, view_textclassifier, view_translation 总计 94 个模块,75,342 行代码
420 lines
15 KiB
Python
420 lines
15 KiB
Python
"""
|
|
Android uwb 组件 — UwbManager, RangingResult, RangingParameters, UwbAddress 等
|
|
方法签名完全对齐 Android SDK (UWB API)
|
|
"""
|
|
|
|
from typing import Any, Callable, Dict, List, Optional
|
|
|
|
from .._core import Stub, AndroidOnlyError
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# UwbConstants
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class UwbConstants(Stub):
|
|
"""UwbConstants — UWB 常量"""
|
|
|
|
STATUS_OK = 0
|
|
STATUS_FAILURE = 1
|
|
STATUS_INVALID_PARAMETERS = 2
|
|
STATUS_SESSION_DOES_NOT_EXIST = 3
|
|
STATUS_MAX_RANGING_ROUND_RETRY = 4
|
|
STATUS_RANGING_TX_FAILED = 5
|
|
STATUS_SESSION_STATE_CHANGE_EXCEPTION = 6
|
|
STATUS_UNKNOWN_ERROR = 255
|
|
|
|
CONFIG_ID_0 = 0
|
|
CONFIG_ID_1 = 1
|
|
CONFIG_ID_2 = 2
|
|
CONFIG_ID_3 = 3
|
|
|
|
MEASUREMENT_REPORT_TYPE_DEFERRED = 0
|
|
MEASUREMENT_REPORT_TYPE_NTF = 1
|
|
|
|
RANGING_UPDATE_RATE_AUTO = 0
|
|
RANGING_UPDATE_RATE_FREQUENCY_1_HZ = 1
|
|
RANGING_UPDATE_RATE_FREQUENCY_2_HZ = 2
|
|
RANGING_UPDATE_RATE_FREQUENCY_5_HZ = 5
|
|
RANGING_UPDATE_RATE_FREQUENCY_10_HZ = 10
|
|
RANGING_UPDATE_RATE_FREQUENCY_20_HZ = 20
|
|
RANGING_UPDATE_RATE_FREQUENCY_100_HZ = 100
|
|
RANGING_UPDATE_RATE_FREQUENCY_250_HZ = 250
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# UwbAddress
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class UwbAddress(Stub):
|
|
"""UwbAddress — UWB 地址"""
|
|
|
|
SHORT_MAC_ADDRESS = 0
|
|
EXTENDED_MAC_ADDRESS = 1
|
|
|
|
def __init__(self, address: bytes = b"", type_: int = SHORT_MAC_ADDRESS):
|
|
super().__init__()
|
|
self._address = address
|
|
self._type = type_
|
|
|
|
def getAddress(self) -> bytes:
|
|
return self._address
|
|
|
|
def getType(self) -> int:
|
|
return self._type
|
|
|
|
def toString(self) -> str:
|
|
return f"UwbAddress(type={self._type}, addr={self._address.hex()})"
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# AngleOfArrival
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class AngleOfArrival(Stub):
|
|
"""AngleOfArrival — 到达角"""
|
|
|
|
STATUS_SUCCESS = 0
|
|
STATUS_FAILURE = 1
|
|
|
|
def __init__(self, azimuth: float = 0.0, elevation: float = 0.0,
|
|
azimuthConfidence: float = 0.0, elevationConfidence: float = 0.0,
|
|
status: int = STATUS_FAILURE):
|
|
super().__init__()
|
|
self._azimuth = azimuth
|
|
self._elevation = elevation
|
|
self._azimuth_confidence = azimuthConfidence
|
|
self._elevation_confidence = elevationConfidence
|
|
self._status = status
|
|
|
|
def getAzimuth(self) -> float:
|
|
return self._azimuth
|
|
|
|
def getElevation(self) -> float:
|
|
return self._elevation
|
|
|
|
def getAzimuthConfidence(self) -> float:
|
|
return self._azimuth_confidence
|
|
|
|
def getElevationConfidence(self) -> float:
|
|
return self._elevation_confidence
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# DistanceMeasurement
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class DistanceMeasurement(Stub):
|
|
"""DistanceMeasurement — 距离测量"""
|
|
|
|
STATUS_SUCCESS = 0
|
|
STATUS_FAILURE = 1
|
|
|
|
def __init__(self, meters: float = 0.0, confidence: float = 0.0,
|
|
standardDeviation: float = 0.0, status: int = STATUS_FAILURE):
|
|
super().__init__()
|
|
self._meters = meters
|
|
self._confidence = confidence
|
|
self._standard_deviation = standardDeviation
|
|
self._status = status
|
|
|
|
def getMeters(self) -> float:
|
|
return self._meters
|
|
|
|
def getConfidence(self) -> float:
|
|
return self._confidence
|
|
|
|
def getStandardDeviation(self) -> float:
|
|
return self._standard_deviation
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# RangingResult
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class RangingResult(Stub):
|
|
"""RangingResult — 测距结果"""
|
|
|
|
def __init__(self, uwbDevice: Any = None, remoteDevice: Any = None,
|
|
status: int = 0, nofRounds: int = 0, nofMeasurements: int = 0,
|
|
elapsedRealtimeNanos: int = 0,
|
|
distanceMeasurement: Optional[DistanceMeasurement] = None,
|
|
angleOfArrival: Optional[AngleOfArrival] = None,
|
|
rssi: float = -90.0):
|
|
super().__init__()
|
|
self._uwb_device = uwbDevice
|
|
self._remote_device = remoteDevice
|
|
self._status = status
|
|
self._nof_rounds = nofRounds
|
|
self._nof_measurements = nofMeasurements
|
|
self._elapsed_realtime_nanos = elapsedRealtimeNanos
|
|
self._distance_measurement = distanceMeasurement
|
|
self._angle_of_arrival = angleOfArrival
|
|
self._rssi = rssi
|
|
self._distance_reported = distanceMeasurement is not None
|
|
self._aoa_reported = angleOfArrival is not None
|
|
|
|
def getUwbDevice(self) -> Any:
|
|
return self._uwb_device
|
|
|
|
def getRemoteDevice(self) -> Any:
|
|
return self._remote_device
|
|
|
|
def getStatus(self) -> int:
|
|
return self._status
|
|
|
|
def getNofRounds(self) -> int:
|
|
return self._nof_rounds
|
|
|
|
def getNofMeasurements(self) -> int:
|
|
return self._nof_measurements
|
|
|
|
def getElapsedRealtimeNanos(self) -> int:
|
|
return self._elapsed_realtime_nanos
|
|
|
|
def getDistanceMeasurement(self) -> Optional[DistanceMeasurement]:
|
|
return self._distance_measurement
|
|
|
|
def getAngleOfArrival(self) -> Optional[AngleOfArrival]:
|
|
return self._angle_of_arrival
|
|
|
|
def getAngleOfArrivalAzimuth(self) -> float:
|
|
if self._angle_of_arrival:
|
|
return self._angle_of_arrival.getAzimuth()
|
|
return 0.0
|
|
|
|
def getAngleOfArrivalElevation(self) -> float:
|
|
if self._angle_of_arrival:
|
|
return self._angle_of_arrival.getElevation()
|
|
return 0.0
|
|
|
|
def getAngleOfArrivalAzimuthConfidence(self) -> float:
|
|
if self._angle_of_arrival:
|
|
return self._angle_of_arrival.getAzimuthConfidence()
|
|
return 0.0
|
|
|
|
def getAngleOfArrivalElevationConfidence(self) -> float:
|
|
if self._angle_of_arrival:
|
|
return self._angle_of_arrival.getElevationConfidence()
|
|
return 0.0
|
|
|
|
def getRssi(self) -> float:
|
|
return self._rssi
|
|
|
|
def isDistanceMeasurementReported(self) -> bool:
|
|
return self._distance_reported
|
|
|
|
def isAngleOfArrivalReported(self) -> bool:
|
|
return self._aoa_reported
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# RangingParameters
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class RangingParameters(Stub):
|
|
"""RangingParameters — 测距参数"""
|
|
|
|
class Builder(Stub):
|
|
"""RangingParameters.Builder — 测距参数构建器"""
|
|
|
|
def __init__(self):
|
|
super().__init__()
|
|
self._uwb_config_id = 0
|
|
self._session_id = 0
|
|
self._sub_session_id = 0
|
|
self._ranging_update_rate = 1
|
|
self._slot_duration = 0
|
|
self._measurement_report_type = 0
|
|
self._number_of_controlee = 1
|
|
self._destination_addresses: List[UwbAddress] = []
|
|
self._device_configs: List[Any] = []
|
|
self._vendor_specific_data: List[Any] = []
|
|
|
|
def setUwbConfigId(self, configId: int) -> "RangingParameters.Builder":
|
|
self._uwb_config_id = configId
|
|
return self
|
|
|
|
def setSessionId(self, sessionId: int) -> "RangingParameters.Builder":
|
|
self._session_id = sessionId
|
|
return self
|
|
|
|
def setSubSessionId(self, subSessionId: int) -> "RangingParameters.Builder":
|
|
self._sub_session_id = subSessionId
|
|
return self
|
|
|
|
def setRangingUpdateRate(self, rate: int) -> "RangingParameters.Builder":
|
|
self._ranging_update_rate = rate
|
|
return self
|
|
|
|
def setSlotDuration(self, duration: int) -> "RangingParameters.Builder":
|
|
self._slot_duration = duration
|
|
return self
|
|
|
|
def setMeasurementReportType(self, reportType: int) -> "RangingParameters.Builder":
|
|
self._measurement_report_type = reportType
|
|
return self
|
|
|
|
def setNumberOfControlee(self, count: int) -> "RangingParameters.Builder":
|
|
self._number_of_controlee = count
|
|
return self
|
|
|
|
def setDestinationAddresses(self, addrs: List[UwbAddress]) -> "RangingParameters.Builder":
|
|
self._destination_addresses = addrs
|
|
return self
|
|
|
|
def setDeviceConfigs(self, configs: List[Any]) -> "RangingParameters.Builder":
|
|
self._device_configs = configs
|
|
return self
|
|
|
|
def setVendorSpecificData(self, data: List[Any]) -> "RangingParameters.Builder":
|
|
self._vendor_specific_data = data
|
|
return self
|
|
|
|
def build(self) -> "RangingParameters":
|
|
rp = RangingParameters()
|
|
rp._uwb_config_id = self._uwb_config_id
|
|
rp._session_id = self._session_id
|
|
rp._sub_session_id = self._sub_session_id
|
|
rp._ranging_update_rate = self._ranging_update_rate
|
|
rp._slot_duration = self._slot_duration
|
|
rp._measurement_report_type = self._measurement_report_type
|
|
rp._number_of_controlee = self._number_of_controlee
|
|
rp._destination_addresses = self._destination_addresses
|
|
rp._device_configs = self._device_configs
|
|
rp._vendor_specific_data = self._vendor_specific_data
|
|
return rp
|
|
|
|
def __init__(self):
|
|
super().__init__()
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# UwbConfiguration / RangingConfig (stubs)
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class UwbConfiguration(Stub):
|
|
"""UwbConfiguration — UWB 配置"""
|
|
|
|
def __init__(self):
|
|
super().__init__()
|
|
|
|
|
|
class RangingConfig(Stub):
|
|
"""RangingConfig — 测距配置"""
|
|
|
|
def __init__(self):
|
|
super().__init__()
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# RangingSession
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class RangingSession(Stub):
|
|
"""RangingSession — 测距会话"""
|
|
|
|
def __init__(self):
|
|
super().__init__()
|
|
self._open = False
|
|
|
|
def open(self):
|
|
self._open = True
|
|
|
|
def close(self):
|
|
self._open = False
|
|
|
|
def reconfigure(self, params: RangingParameters):
|
|
pass
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# UwbManager
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class UwbManager(Stub):
|
|
"""UwbManager — UWB 管理器"""
|
|
|
|
# ═══════════════════════════════════════════════════════════
|
|
# UwbCallback
|
|
# ═══════════════════════════════════════════════════════════
|
|
|
|
class UwbCallback(Stub):
|
|
"""UwbManager.UwbCallback — UWB 回调"""
|
|
|
|
def onRangingResult(self, sessionId: int, result: RangingResult):
|
|
pass
|
|
|
|
def onRangingFailure(self, sessionId: int, reason: int):
|
|
pass
|
|
|
|
def onControleeResult(self, sessionId: int, status: int):
|
|
pass
|
|
|
|
_instance: Optional["UwbManager"] = None
|
|
|
|
def __init__(self):
|
|
super().__init__()
|
|
|
|
@staticmethod
|
|
def getInstance(context: Any = None) -> "UwbManager":
|
|
if UwbManager._instance is None:
|
|
UwbManager._instance = UwbManager()
|
|
return UwbManager._instance
|
|
|
|
def open(self, sessionId: int) -> RangingSession:
|
|
session = RangingSession()
|
|
session.open()
|
|
return session
|
|
|
|
def close(self, sessionId: int):
|
|
pass
|
|
|
|
def range(self, sessionId: int, params: RangingParameters,
|
|
callback: UwbCallback):
|
|
if callback:
|
|
result = RangingResult(
|
|
status=UwbConstants.STATUS_OK,
|
|
distanceMeasurement=DistanceMeasurement(
|
|
meters=1.5, confidence=0.8,
|
|
standardDeviation=0.1, status=DistanceMeasurement.STATUS_SUCCESS
|
|
),
|
|
rssi=-65.0
|
|
)
|
|
callback.onRangingResult(sessionId, result)
|
|
|
|
def stopRange(self, sessionId: int):
|
|
pass
|
|
|
|
def addControlee(self, sessionId: int, address: UwbAddress):
|
|
pass
|
|
|
|
def removeControlee(self, sessionId: int, address: UwbAddress):
|
|
pass
|
|
|
|
def setMeasurementData(self, sessionId: int, data: bytes):
|
|
pass
|
|
|
|
def sendMeasurementData(self, sessionId: int, data: bytes):
|
|
pass
|
|
|
|
def getUwbDevice(self) -> Any:
|
|
return None
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# __all__
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
__all__ = [
|
|
"UwbManager",
|
|
"UwbConstants",
|
|
"UwbAddress",
|
|
"AngleOfArrival",
|
|
"DistanceMeasurement",
|
|
"RangingResult",
|
|
"RangingParameters",
|
|
"UwbConfiguration",
|
|
"RangingConfig",
|
|
"RangingSession",
|
|
] |