- android/ 167个模块 (app/content/os/view/widget/graphics/media/hardware/net/telephony/provider等) - java/ 35个模块 (lang/io/util/net/nio/security/crypto/sql/beans/rmi/awt等) - javax/ 4个模块 (net/crypto/security/sql) - org/ 5个模块 (json/w3c_dom/xml_sax/xml_pull/apache_http) - dalvik/ 1个模块 (system) - ~3053个类/接口,方法签名完全对齐Android SDK - 桌面跨平台运行 (Windows/macOS/Linux) - 修复所有导入错误和Python关键字冲突
417 lines
14 KiB
Python
417 lines
14 KiB
Python
"""
|
|
Android hardware.radio 组件 — RadioManager, RadioTuner, RadioMetadata 等
|
|
方法签名完全对齐 Android SDK
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import threading
|
|
from typing import Any, Callable, Dict, List, Optional, Set
|
|
|
|
from .._core import Stub, AndroidOnlyError
|
|
from ..java.lang import RuntimeException
|
|
|
|
IllegalArgumentException = type("IllegalArgumentException", (RuntimeException,), {})
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# RadioMetadata
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class RadioMetadata(Stub):
|
|
"""RadioMetadata — 收音机元数据"""
|
|
|
|
METADATA_KEY_ART = 0x00000001
|
|
METADATA_KEY_ARTIST = 0x00000002
|
|
METADATA_KEY_TITLE = 0x00000003
|
|
METADATA_KEY_ALBUM = 0x00000004
|
|
METADATA_KEY_GENRE = 0x00000005
|
|
METADATA_KEY_CLOCK = 0x00000006
|
|
METADATA_KEY_ICON = 0x00000007
|
|
METADATA_KEY_RDS_PI = 0x00000008
|
|
METADATA_KEY_RDS_PS = 0x00000009
|
|
METADATA_KEY_RDS_RT = 0x0000000A
|
|
METADATA_KEY_DAB_ENSEMBLE_NAME = 0x0000000B
|
|
METADATA_KEY_DAB_ECC = 0x0000000C
|
|
METADATA_KEY_DAB_IDENTIFIER = 0x0000000D
|
|
METADATA_KEY_DAB_SERVICE_NAME = 0x0000000E
|
|
|
|
def __init__(self):
|
|
super().__init__()
|
|
self._data: Dict[int, Any] = {}
|
|
|
|
def getString(self, key: int) -> Optional[str]:
|
|
val = self._data.get(key)
|
|
return str(val) if val is not None else None
|
|
|
|
def getInt(self, key: int) -> int:
|
|
return int(self._data.get(key, 0))
|
|
|
|
def getLong(self, key: int) -> int:
|
|
return int(self._data.get(key, 0))
|
|
|
|
def getBitmap(self, key: int) -> Any:
|
|
return self._data.get(key)
|
|
|
|
def getText(self, key: int) -> Optional[str]:
|
|
return self.getString(key)
|
|
|
|
def containsKey(self, key: int) -> bool:
|
|
return key in self._data
|
|
|
|
def keySet(self) -> Set[int]:
|
|
return set(self._data.keys())
|
|
|
|
def putString(self, key: int, value: str):
|
|
self._data[key] = value
|
|
|
|
def putInt(self, key: int, value: int):
|
|
self._data[key] = value
|
|
|
|
def toString(self) -> str:
|
|
return f"RadioMetadata{{{len(self._data)} entries}}"
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# RadioManager.ProgramInfo
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class RadioManager:
|
|
"""RadioManager — 收音机管理器(命名空间)"""
|
|
|
|
STATUS_SUCCESS = 0
|
|
STATUS_ERROR = -1
|
|
STATUS_INVALID_ARGUMENTS = -2
|
|
STATUS_INVALID_OPERATION = -3
|
|
STATUS_NO_ENTRY = -4
|
|
STATUS_PERMISSION_DENIED = -5
|
|
STATUS_NOT_SUPPORTED = -6
|
|
STATUS_NOT_INITIALIZED = -7
|
|
STATUS_BUSY = -8
|
|
STATUS_TIMED_OUT = -9
|
|
STATUS_DEAD_OBJECT = -10
|
|
|
|
|
|
class RadioManager_ProgramInfo(Stub):
|
|
"""RadioManager.ProgramInfo — 节目信息"""
|
|
|
|
INFO_TYPE_MIN = 0
|
|
INFO_TYPE_MAX = 1
|
|
|
|
def __init__(self):
|
|
super().__init__()
|
|
self._metadata = RadioMetadata()
|
|
self._info_type: int = 0
|
|
self._channel: int = 0
|
|
self._tuning_frequency: int = 0
|
|
self._program_type: int = 0
|
|
self._digital: bool = False
|
|
self._emergency: bool = False
|
|
self._traffic: bool = False
|
|
self._music: bool = False
|
|
self._news: bool = False
|
|
self._talk: bool = False
|
|
self._sport: bool = False
|
|
self._weather: bool = False
|
|
self._classical: bool = False
|
|
|
|
def getRadioMetadata(self) -> RadioMetadata:
|
|
return self._metadata
|
|
|
|
def getInfoType(self) -> int:
|
|
return self._info_type
|
|
|
|
def getChannel(self) -> int:
|
|
return self._channel
|
|
|
|
def getTuningFrequency(self) -> int:
|
|
return self._tuning_frequency
|
|
|
|
def getProgramType(self) -> int:
|
|
return self._program_type
|
|
|
|
def isDigital(self) -> bool:
|
|
return self._digital
|
|
|
|
def isEmergency(self) -> bool:
|
|
return self._emergency
|
|
|
|
def isTraffic(self) -> bool:
|
|
return self._traffic
|
|
|
|
def isMusic(self) -> bool:
|
|
return self._music
|
|
|
|
def isNews(self) -> bool:
|
|
return self._news
|
|
|
|
def isTalk(self) -> bool:
|
|
return self._talk
|
|
|
|
def isSport(self) -> bool:
|
|
return self._sport
|
|
|
|
def isWeather(self) -> bool:
|
|
return self._weather
|
|
|
|
def isClassical(self) -> bool:
|
|
return self._classical
|
|
|
|
def toString(self) -> str:
|
|
return f"ProgramInfo{{channel={self._channel}, digital={self._digital}}}"
|
|
|
|
|
|
RadioManager.ProgramInfo = RadioManager_ProgramInfo
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# RadioManager.ModuleProperties
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class RadioManager_ModuleProperties(Stub):
|
|
"""RadioManager.ModuleProperties — 模块属性"""
|
|
|
|
def __init__(self, id_: int = 0, service_name: str = "radio",
|
|
class_id: int = 0, implementor: str = "Android-pyApi",
|
|
hal_version: int = 2,
|
|
supported_program_types: Optional[List[int]] = None,
|
|
supported_sound_bands: Optional[List[int]] = None,
|
|
supported_deemphasis: Optional[List[int]] = None,
|
|
supported_regions: Optional[List[int]] = None,
|
|
min_freq: int = 87500, max_freq: int = 108000,
|
|
freq_step: int = 100):
|
|
super().__init__()
|
|
self._id = id_
|
|
self._service_name = service_name
|
|
self._class_id = class_id
|
|
self._implementor = implementor
|
|
self._hal_version = hal_version
|
|
self._supported_program_types = supported_program_types or [0, 1]
|
|
self._supported_sound_bands = supported_sound_bands or [0]
|
|
self._supported_deemphasis = supported_deemphasis or [50]
|
|
self._supported_regions = supported_regions or [0]
|
|
self._min_freq = min_freq
|
|
self._max_freq = max_freq
|
|
self._freq_step = freq_step
|
|
self._vendor_info: Dict[str, str] = {}
|
|
self._initialization_complete: bool = True
|
|
self._bg_scan_available: bool = True
|
|
self._program_info_available: bool = True
|
|
self._antenna_connected: bool = True
|
|
|
|
def getId(self) -> int:
|
|
return self._id
|
|
|
|
def getServiceName(self) -> str:
|
|
return self._service_name
|
|
|
|
def getClassId(self) -> int:
|
|
return self._class_id
|
|
|
|
def getImplementor(self) -> str:
|
|
return self._implementor
|
|
|
|
def getHALVersion(self) -> int:
|
|
return self._hal_version
|
|
|
|
def getSupportedProgramTypes(self) -> List[int]:
|
|
return list(self._supported_program_types)
|
|
|
|
def getSupportedSoundBands(self) -> List[int]:
|
|
return list(self._supported_sound_bands)
|
|
|
|
def getSupportedDeemphasis(self) -> List[int]:
|
|
return list(self._supported_deemphasis)
|
|
|
|
def getSupportedRegions(self) -> List[int]:
|
|
return list(self._supported_regions)
|
|
|
|
def getMinTuningFrequency(self) -> int:
|
|
return self._min_freq
|
|
|
|
def getMaxTuningFrequency(self) -> int:
|
|
return self._max_freq
|
|
|
|
def getTuningFrequencyStep(self) -> int:
|
|
return self._freq_step
|
|
|
|
def getVendorInfo(self) -> Dict[str, str]:
|
|
return dict(self._vendor_info)
|
|
|
|
def isInitializationComplete(self) -> bool:
|
|
return self._initialization_complete
|
|
|
|
def isBgScanAvailable(self) -> bool:
|
|
return self._bg_scan_available
|
|
|
|
def isProgramInfoAvailable(self) -> bool:
|
|
return self._program_info_available
|
|
|
|
def isAntennaConnected(self) -> bool:
|
|
return self._antenna_connected
|
|
|
|
def toString(self) -> str:
|
|
return f"ModuleProperties{{id={self._id}, name={self._service_name}}}"
|
|
|
|
|
|
RadioManager.ModuleProperties = RadioManager_ModuleProperties
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# RadioTuner
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class RadioTuner(Stub):
|
|
"""RadioTuner — 收音机调谐器"""
|
|
|
|
DIRECTION_DOWN = 0
|
|
DIRECTION_UP = 1
|
|
|
|
def __init__(self):
|
|
super().__init__()
|
|
self._frequency: int = 100000 # 100 MHz
|
|
self._muted: bool = False
|
|
self._configuration: Optional[Dict[str, Any]] = None
|
|
|
|
def scan(self, direction: int, skipSubChannel: bool = False) -> int:
|
|
step = 100 if direction == self.DIRECTION_UP else -100
|
|
self._frequency += step
|
|
return RadioManager.STATUS_SUCCESS
|
|
|
|
def step(self, direction: int, skipSubChannel: bool = False) -> int:
|
|
return self.scan(direction, skipSubChannel)
|
|
|
|
def tune(self, frequency: int, programType: int = -1) -> int:
|
|
self._frequency = frequency
|
|
return RadioManager.STATUS_SUCCESS
|
|
|
|
def cancel(self) -> int:
|
|
return RadioManager.STATUS_SUCCESS
|
|
|
|
def cancelAnnouncement(self) -> int:
|
|
return RadioManager.STATUS_SUCCESS
|
|
|
|
def getConfiguration(self) -> Optional[Dict[str, Any]]:
|
|
return self._configuration
|
|
|
|
def setConfiguration(self, configuration: Dict[str, Any]) -> int:
|
|
self._configuration = dict(configuration)
|
|
return RadioManager.STATUS_SUCCESS
|
|
|
|
def getMute(self) -> bool:
|
|
return self._muted
|
|
|
|
def setMute(self, mute: bool) -> int:
|
|
self._muted = mute
|
|
return RadioManager.STATUS_SUCCESS
|
|
|
|
def getProgramInformation(self, fullInfo: bool = True) -> Optional[RadioManager.ProgramInfo]:
|
|
info = RadioManager.ProgramInfo()
|
|
info._tuning_frequency = self._frequency
|
|
return info
|
|
|
|
def isAntennaConnected(self) -> bool:
|
|
return True
|
|
|
|
def hasControl(self) -> bool:
|
|
return True
|
|
|
|
def getParameters(self, keys: List[str]) -> Dict[str, str]:
|
|
return {}
|
|
|
|
def setParameters(self, parameters: Dict[str, str]) -> int:
|
|
return RadioManager.STATUS_SUCCESS
|
|
|
|
def close(self):
|
|
pass
|
|
|
|
def toString(self) -> str:
|
|
return f"RadioTuner{{frequency={self._frequency}}}"
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# RadioManager (main class)
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class RadioManager(Stub):
|
|
"""RadioManager — 收音机管理器"""
|
|
|
|
STATUS_SUCCESS = 0
|
|
STATUS_ERROR = -1
|
|
STATUS_INVALID_ARGUMENTS = -2
|
|
STATUS_INVALID_OPERATION = -3
|
|
STATUS_NO_ENTRY = -4
|
|
STATUS_PERMISSION_DENIED = -5
|
|
STATUS_NOT_SUPPORTED = -6
|
|
STATUS_NOT_INITIALIZED = -7
|
|
STATUS_BUSY = -8
|
|
STATUS_TIMED_OUT = -9
|
|
STATUS_DEAD_OBJECT = -10
|
|
|
|
def __init__(self):
|
|
super().__init__()
|
|
self._lock = threading.Lock()
|
|
self._modules: List[RadioManager.ModuleProperties] = [
|
|
RadioManager.ModuleProperties(id_=0, service_name="FM Radio"),
|
|
]
|
|
self._tuner: Optional[RadioTuner] = None
|
|
self._enabled: bool = False
|
|
self._callbacks: List[Any] = []
|
|
|
|
def listModules(self, modules: List[Any]) -> int:
|
|
modules.clear()
|
|
modules.extend(self._modules)
|
|
return self.STATUS_SUCCESS
|
|
|
|
def open(self, moduleId: int, tunerCallback: Any) -> Optional[RadioTuner]:
|
|
self._tuner = RadioTuner()
|
|
return self._tuner
|
|
|
|
def close(self, tuner: RadioTuner):
|
|
tuner.close()
|
|
self._tuner = None
|
|
|
|
def getModuleProperties(self, moduleId: int) -> Optional[RadioManager.ModuleProperties]:
|
|
for m in self._modules:
|
|
if m.getId() == moduleId:
|
|
return m
|
|
return None
|
|
|
|
def getParameters(self, moduleId: int, keys: List[str]) -> Dict[str, str]:
|
|
return {}
|
|
|
|
def setParameters(self, moduleId: int, parameters: Dict[str, str]) -> int:
|
|
return self.STATUS_SUCCESS
|
|
|
|
def isEnabled(self) -> bool:
|
|
return self._enabled
|
|
|
|
def registerCallback(self, callback: Any, handler: Any = None) -> int:
|
|
if callback not in self._callbacks:
|
|
self._callbacks.append(callback)
|
|
return self.STATUS_SUCCESS
|
|
|
|
def unregisterCallback(self, callback: Any) -> int:
|
|
if callback in self._callbacks:
|
|
self._callbacks.remove(callback)
|
|
return self.STATUS_SUCCESS
|
|
|
|
def registerClient(self, packageName: str, callback: Any) -> int:
|
|
return self.STATUS_SUCCESS
|
|
|
|
def unregisterClient(self, packageName: str) -> int:
|
|
return self.STATUS_SUCCESS
|
|
|
|
def toString(self) -> str:
|
|
return f"RadioManager@{hex(id(self))}"
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# __all__
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
__all__ = [
|
|
"RadioManager",
|
|
"RadioTuner",
|
|
"RadioMetadata",
|
|
] |