""" Android Telephony 组件 — TelephonyManager, CellInfo, PhoneStateListener 等 方法签名完全对齐 Android SDK """ import os import sys import random from typing import Any, Dict, List, Optional, Set, Tuple, Union from .._core import ( Stub, AndroidOnlyError, android_context, resolve_android_path, to_android_path, _sdcard_root, _app_data_dir, _package_name, ) try: from .._linux_impl import IS_LINUX, LinuxNetwork, LinuxProcess, LinuxLocation _USE_LINUX = IS_LINUX except ImportError: _USE_LINUX = False # ═══════════════════════════════════════════════════════════════ # CellIdentity 基类集合 # ═══════════════════════════════════════════════════════════════ class CellIdentity(Stub): def __init__(self): super().__init__() class CellIdentityGsm(CellIdentity): def __init__(self, mcc: int = 0, mnc: int = 0, lac: int = 0, cid: int = 0, arfcn: int = 0): super().__init__() self._mcc = mcc self._mnc = mnc self._lac = lac self._cid = cid self._arfcn = arfcn def getMcc(self) -> int: return self._mcc def getMnc(self) -> int: return self._mnc def getLac(self) -> int: return self._lac def getCid(self) -> int: return self._cid def getArfcn(self) -> int: return self._arfcn class CellIdentityCdma(CellIdentity): def __init__(self, network_id: int = 0, system_id: int = 0, basestation_id: int = 0, latitude: int = 0, longitude: int = 0): super().__init__() self._network_id = network_id self._system_id = system_id self._basestation_id = basestation_id self._latitude = latitude self._longitude = longitude def getNetworkId(self) -> int: return self._network_id def getSystemId(self) -> int: return self._system_id def getBasestationId(self) -> int: return self._basestation_id def getLatitude(self) -> int: return self._latitude def getLongitude(self) -> int: return self._longitude class CellIdentityLte(CellIdentity): def __init__(self, mcc: int = 0, mnc: int = 0, ci: int = 0, pci: int = 0, tac: int = 0): super().__init__() self._mcc = mcc; self._mnc = mnc self._ci = ci; self._pci = pci; self._tac = tac def getMcc(self) -> int: return self._mcc def getMnc(self) -> int: return self._mnc def getCi(self) -> int: return self._ci def getPci(self) -> int: return self._pci def getTac(self) -> int: return self._tac class CellIdentityWcdma(CellIdentity): def __init__(self, mcc: int = 0, mnc: int = 0, lac: int = 0, cid: int = 0, psc: int = 0): super().__init__() self._mcc = mcc; self._mnc = mnc self._lac = lac; self._cid = cid; self._psc = psc def getMcc(self) -> int: return self._mcc def getMnc(self) -> int: return self._mnc def getLac(self) -> int: return self._lac def getCid(self) -> int: return self._cid def getPsc(self) -> int: return self._psc class CellIdentityNr(CellIdentity): def __init__(self, mcc: int = 0, mnc: int = 0, nci: int = 0, pci: int = 0, tac: int = 0): super().__init__() self._mcc = mcc; self._mnc = mnc self._nci = nci; self._pci = pci; self._tac = tac def getMcc(self) -> int: return self._mcc def getMnc(self) -> int: return self._mnc def getNci(self) -> int: return self._nci def getPci(self) -> int: return self._pci def getTac(self) -> int: return self._tac # ═══════════════════════════════════════════════════════════════ # CellSignalStrength 基类集合 # ═══════════════════════════════════════════════════════════════ class CellSignalStrength(Stub): SIGNAL_STRENGTH_NONE_OR_UNKNOWN = 0 SIGNAL_STRENGTH_POOR = 1 SIGNAL_STRENGTH_MODERATE = 2 SIGNAL_STRENGTH_GOOD = 3 SIGNAL_STRENGTH_GREAT = 4 def getLevel(self) -> int: return self.SIGNAL_STRENGTH_NONE_OR_UNKNOWN def getAsuLevel(self) -> int: return 0 def getDbm(self) -> int: return 0 class CellSignalStrengthGsm(CellSignalStrength): def __init__(self, rssi: int = 0, ber: int = 0, ta: int = 0): super().__init__() self._rssi = rssi; self._ber = ber; self._ta = ta def getRssi(self) -> int: return self._rssi def getDbm(self) -> int: return self._rssi - 113 if self._rssi > 0 else 0 class CellSignalStrengthCdma(CellSignalStrength): def __init__(self, dbm: int = 0, ecio: int = 0, evdo_dbm: int = 0, evdo_ecio: int = 0, evdo_snr: int = 0): super().__init__() self._dbm = dbm; self._ecio = ecio self._evdo_dbm = evdo_dbm; self._evdo_ecio = evdo_ecio; self._evdo_snr = evdo_snr def getDbm(self) -> int: return self._dbm class CellSignalStrengthLte(CellSignalStrength): def __init__(self, rssi: int = 0, rsrp: int = 0, rsrq: int = 0, rssnr: int = 0, cqi: int = 0, ta: int = 0): super().__init__() self._rssi = rssi; self._rsrp = rsrp; self._rsrq = rsrq self._rssnr = rssnr; self._cqi = cqi; self._ta = ta def getRsrp(self) -> int: return self._rsrp def getRsrq(self) -> int: return self._rsrq def getRssnr(self) -> int: return self._rssnr def getDbm(self) -> int: return self._rsrp class CellSignalStrengthWcdma(CellSignalStrength): def __init__(self, rscp: int = 0, ecno: int = 0): super().__init__() self._rscp = rscp; self._ecno = ecno def getRscp(self) -> int: return self._rscp def getEcno(self) -> int: return self._ecno def getDbm(self) -> int: return self._rscp - 113 if self._rscp > 0 else 0 class CellSignalStrengthNr(CellSignalStrength): def __init__(self, ssRsrp: int = 0, ssRsrq: int = 0, ssSinr: int = 0, csiRsrp: int = 0): super().__init__() self._ssRsrp = ssRsrp; self._ssRsrq = ssRsrq self._ssSinr = ssSinr; self._csiRsrp = csiRsrp def getSsRsrp(self) -> int: return self._ssRsrp def getDbm(self) -> int: return self._ssRsrp # ═══════════════════════════════════════════════════════════════ # CellInfo 基类集合 # ═══════════════════════════════════════════════════════════════ class CellInfo(Stub): UNAVAILABLE = 0x7FFFFFFF TIMESTAMP_TYPE_UNKNOWN = 0 TIMESTAMP_TYPE_GSM = 1 TIMESTAMP_TYPE_UMTS = 2 TIMESTAMP_TYPE_CDMA = 3 TIMESTAMP_TYPE_LTE = 4 TIMESTAMP_TYPE_WCDMA = 5 TIMESTAMP_TYPE_NR = 6 def __init__(self): super().__init__() self._registered = False self._timestamp = 0 self._connection_status = 0 def isRegistered(self) -> bool: return self._registered def getTimeStamp(self) -> int: return self._timestamp def getCellConnectionStatus(self) -> int: return self._connection_status class CellInfoGsm(CellInfo): def __init__(self): super().__init__() self._identity = CellIdentityGsm() self._signal_strength = CellSignalStrengthGsm() def getCellIdentity(self) -> CellIdentityGsm: return self._identity def getCellSignalStrength(self) -> CellSignalStrengthGsm: return self._signal_strength class CellInfoCdma(CellInfo): def __init__(self): super().__init__() self._identity = CellIdentityCdma() self._signal_strength = CellSignalStrengthCdma() def getCellIdentity(self) -> CellIdentityCdma: return self._identity def getCellSignalStrength(self) -> CellSignalStrengthCdma: return self._signal_strength class CellInfoLte(CellInfo): def __init__(self): super().__init__() self._identity = CellIdentityLte() self._signal_strength = CellSignalStrengthLte() def getCellIdentity(self) -> CellIdentityLte: return self._identity def getCellSignalStrength(self) -> CellSignalStrengthLte: return self._signal_strength class CellInfoWcdma(CellInfo): def __init__(self): super().__init__() self._identity = CellIdentityWcdma() self._signal_strength = CellSignalStrengthWcdma() def getCellIdentity(self) -> CellIdentityWcdma: return self._identity def getCellSignalStrength(self) -> CellSignalStrengthWcdma: return self._signal_strength class CellInfoNr(CellInfo): def __init__(self): super().__init__() self._identity = CellIdentityNr() self._signal_strength = CellSignalStrengthNr() def getCellIdentity(self) -> CellIdentityNr: return self._identity def getCellSignalStrength(self) -> CellSignalStrengthNr: return self._signal_strength # ═══════════════════════════════════════════════════════════════ # PhoneStateListener # ═══════════════════════════════════════════════════════════════ class PhoneStateListener(Stub): LISTEN_NONE = 0 LISTEN_SERVICE_STATE = 1 LISTEN_SIGNAL_STRENGTHS = 2 LISTEN_MESSAGE_WAITING_INDICATOR = 4 LISTEN_CALL_FORWARDING_INDICATOR = 8 LISTEN_CELL_LOCATION = 16 LISTEN_CALL_STATE = 32 LISTEN_DATA_CONNECTION_STATE = 64 LISTEN_DATA_ACTIVITY = 128 LISTEN_SIGNAL_STRENGTH = 256 LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH = 512 LISTEN_CELL_INFO = 1024 LISTEN_PRECISE_CALL_STATE = 2048 LISTEN_PRECISE_DATA_CONNECTION_STATE = 4096 LISTEN_DATA_CONNECTION_REAL_TIME_INFO = 8192 LISTEN_OEM_HOOK_RAW_EVENT = 32768 LISTEN_SRVCC_STATE_CHANGED = 65536 LISTEN_CARRIER_NETWORK_CHANGE = 131072 LISTEN_VOICE_ACTIVATION_STATE = 262144 LISTEN_DATA_ACTIVATION_STATE = 524288 LISTEN_USER_MOBILE_DATA_STATE = 1048576 LISTEN_DISPLAY_INFO_CHANGED = 2097152 LISTEN_PHONE_CAPABILITY_CHANGE = 4194304 LISTEN_ACTIVE_PHONE_TYPE_CHANGE = 8388608 LISTEN_EMERGENCY_NUMBER_LIST = 16777216 LISTEN_EMERGENCY_NUMBER_SOURCE = 33554432 LISTEN_CALL_ATTRIBUTES_CHANGED = 67108864 LISTEN_BARRING_INFO_CHANGED = 134217728 LISTEN_ALL = 2147483647 def __init__(self, looper: Any = None): super().__init__() self._looper = looper def onServiceStateChanged(self, service_state: "ServiceState"): pass def onSignalStrengthsChanged(self, signal_strength: "SignalStrength"): pass def onMessageWaitingIndicatorChanged(self, mwi: bool): pass def onCallForwardingIndicatorChanged(self, cfi: bool): pass def onCellLocationChanged(self, location: Any): pass def onCallStateChanged(self, state: int, phone_number: str): pass def onDataConnectionStateChanged(self, state: int, network_type: int = 0): pass def onDataActivity(self, direction: int): pass def onSignalStrengthChanged(self, asu: int): pass def onCellInfoChanged(self, cell_info: List[CellInfo]): pass # ═══════════════════════════════════════════════════════════════ # ServiceState / SignalStrength # ═══════════════════════════════════════════════════════════════ class ServiceState(Stub): STATE_IN_SERVICE = 0 STATE_OUT_OF_SERVICE = 1 STATE_EMERGENCY_ONLY = 2 STATE_POWER_OFF = 3 def __init__(self): super().__init__() self._state = self.STATE_OUT_OF_SERVICE self._roaming = False self._operator_alpha_long: str = "" self._operator_alpha_short: str = "" self._operator_numeric: str = "" self._is_manual_selection = False self._cdma_default_roaming_indicator = -1 self._cdma_eri_icon_index = -1 self._cdma_eri_icon_mode = -1 self._cdma_roaming_indicator = -1 self._channel_number = 0 def getState(self) -> int: return self._state def setState(self, state: int): self._state = state def getRoaming(self) -> bool: return self._roaming def setRoaming(self, roaming: bool): self._roaming = roaming def getOperatorAlphaLong(self) -> str: return self._operator_alpha_long def getOperatorAlphaShort(self) -> str: return self._operator_alpha_short def getOperatorNumeric(self) -> str: return self._operator_numeric def getIsManualSelection(self) -> bool: return self._is_manual_selection def getCdmaDefaultRoamingIndicator(self) -> int: return self._cdma_default_roaming_indicator def getCdmaEriIconIndex(self) -> int: return self._cdma_eri_icon_index def getCdmaEriIconMode(self) -> int: return self._cdma_eri_icon_mode def getCdmaRoamingIndicator(self) -> int: return self._cdma_roaming_indicator def getChannelNumber(self) -> int: return self._channel_number def getNetworkRegistrationInfo(self, domain: int, transport_type: int) -> Any: return None def toString(self) -> str: return f"ServiceState(state={self._state}, roaming={self._roaming})" class SignalStrength(Stub): NUM_SIGNAL_STRENGTH_BINS = 5 SIGNAL_STRENGTH_NONE_OR_UNKNOWN = 0 SIGNAL_STRENGTH_POOR = 1 SIGNAL_STRENGTH_MODERATE = 2 SIGNAL_STRENGTH_GOOD = 3 SIGNAL_STRENGTH_GREAT = 4 def __init__(self): super().__init__() self._gsm_signal_strength = 0 self._cdma_dbm = 0 self._cdma_ecio = 0 self._evdo_dbm = 0 self._evdo_ecio = 0 self._evdo_snr = 0 self._lte_signal_strength = 0 self._td_scdma_rscp = 0 def getGsmSignalStrength(self) -> int: return self._gsm_signal_strength def getCdmaDbm(self) -> int: return self._cdma_dbm def getCdmaEcio(self) -> int: return self._cdma_ecio def getEvdoDbm(self) -> int: return self._evdo_dbm def getEvdoEcio(self) -> int: return self._evdo_ecio def getEvdoSnr(self) -> int: return self._evdo_snr def getLteSignalStrength(self) -> int: return self._lte_signal_strength def getLevel(self) -> int: return self.SIGNAL_STRENGTH_NONE_OR_UNKNOWN def getAsuLevel(self) -> int: return 0 def getDbm(self) -> int: return 0 # ═══════════════════════════════════════════════════════════════ # SmsManager # ═══════════════════════════════════════════════════════════════ class SmsManager(Stub): RESULT_ERROR_GENERIC_FAILURE = 1 RESULT_ERROR_RADIO_OFF = 2 RESULT_ERROR_NULL_PDU = 3 RESULT_ERROR_NO_SERVICE = 4 RESULT_ERROR_LIMIT_EXCEEDED = 5 RESULT_ERROR_FDN_CHECK_FAILURE = 6 RESULT_ERROR_SHORT_CODE_NOT_ALLOWED = 7 RESULT_ERROR_SHORT_CODE_NEVER_ALLOWED = 8 RESULT_RIL_GENERIC_FAILURE = 9 RESULT_RIL_RADIO_NOT_AVAILABLE = 10 STATUS_ON_ICC_FREE = 0 STATUS_ON_ICC_READ = 1 STATUS_ON_ICC_UNREAD = 3 STATUS_ON_ICC_SENT = 5 STATUS_ON_ICC_UNSENT = 7 _instance: Optional["SmsManager"] = None def __init__(self): super().__init__() @staticmethod def getDefault() -> "SmsManager": if SmsManager._instance is None: SmsManager._instance = SmsManager() return SmsManager._instance def sendTextMessage(self, dest_address: str, sc_address: Optional[str], text: str, sent_intent: Any, delivery_intent: Any): pass def sendMultipartTextMessage(self, dest_address: str, sc_address: Optional[str], parts: List[str], sent_intents: Optional[List[Any]], delivery_intents: Optional[List[Any]]): pass def sendDataMessage(self, dest_address: str, sc_address: Optional[str], dest_port: int, data: bytes, sent_intent: Any, delivery_intent: Any): pass def sendMultimediaMessage(self, context: Any, content_uri: str, location_url: Optional[str], config_overrides: Optional[Any], sent_intent: Any): pass # ═══════════════════════════════════════════════════════════════ # PhoneNumberUtils # ═══════════════════════════════════════════════════════════════ class PhoneNumberUtils(Stub): FORMAT_JAPAN = 2 FORMAT_NANP = 1 FORMAT_UNKNOWN = 0 @staticmethod def formatNumber(source: str) -> str: return source @staticmethod def isGlobalPhoneNumber(phone_number: str) -> bool: return bool(phone_number and len(phone_number) >= 7) @staticmethod def compare(a: str, b: str) -> bool: return a.replace("-", "").replace(" ", "") == b.replace("-", "").replace(" ", "") @staticmethod def formatNumberToE164(phone_number: str, default_country_iso: str) -> Optional[str]: return phone_number @staticmethod def formatNumberToRFC3966(phone_number: str, default_country_iso: str) -> Optional[str]: return phone_number @staticmethod def isEmergencyNumber(phone_number: str) -> bool: return phone_number in ("911", "112", "999", "000", "110", "119", "120", "122") @staticmethod def isVoiceMailNumber(phone_number: str) -> bool: return False @staticmethod def convertKeypadLettersToDigits(input_: str) -> str: mapping = {"A": "2", "B": "2", "C": "2", "D": "3", "E": "3", "F": "3", "G": "4", "H": "4", "I": "4", "J": "5", "K": "5", "L": "5", "M": "6", "N": "6", "O": "6", "P": "7", "Q": "7", "R": "7", "S": "7", "T": "8", "U": "8", "V": "8", "W": "9", "X": "9", "Y": "9", "Z": "9"} result = "" for c in input_.upper(): result += mapping.get(c, c) return result @staticmethod def toCallerIDMinMatch(phone_number: str) -> str: return phone_number[-7:] if len(phone_number) >= 7 else phone_number # ═══════════════════════════════════════════════════════════════ # TelephonyManager # ═══════════════════════════════════════════════════════════════ class TelephonyManager(Stub): """TelephonyManager — 电话管理器""" PHONE_TYPE_NONE = 0 PHONE_TYPE_GSM = 1 PHONE_TYPE_CDMA = 2 PHONE_TYPE_SIP = 3 NETWORK_TYPE_UNKNOWN = 0 NETWORK_TYPE_GPRS = 1 NETWORK_TYPE_EDGE = 2 NETWORK_TYPE_UMTS = 3 NETWORK_TYPE_CDMA = 4 NETWORK_TYPE_EVDO_0 = 5 NETWORK_TYPE_EVDO_A = 6 NETWORK_TYPE_1xRTT = 7 NETWORK_TYPE_HSDPA = 8 NETWORK_TYPE_HSUPA = 9 NETWORK_TYPE_HSPA = 10 NETWORK_TYPE_IDEN = 11 NETWORK_TYPE_EVDO_B = 12 NETWORK_TYPE_LTE = 13 NETWORK_TYPE_EHRPD = 14 NETWORK_TYPE_HSPAP = 15 NETWORK_TYPE_GSM = 16 NETWORK_TYPE_TD_SCDMA = 17 NETWORK_TYPE_IWLAN = 18 NETWORK_TYPE_LTE_CA = 19 NETWORK_TYPE_NR = 20 SIM_STATE_UNKNOWN = 0 SIM_STATE_ABSENT = 1 SIM_STATE_PIN_REQUIRED = 2 SIM_STATE_PUK_REQUIRED = 3 SIM_STATE_NETWORK_LOCKED = 4 SIM_STATE_READY = 5 SIM_STATE_NOT_READY = 6 SIM_STATE_PERM_DISABLED = 7 DATA_DISCONNECTED = 0 DATA_CONNECTING = 1 DATA_CONNECTED = 2 DATA_SUSPENDED = 3 CALL_STATE_IDLE = 0 CALL_STATE_RINGING = 1 CALL_STATE_OFFHOOK = 2 def __init__(self, context: Any = None): super().__init__() self._context = context def getNetworkOperatorName(self) -> str: if _USE_LINUX: loc = LinuxLocation.get_location() return loc.get("isp", "") or "" return "MockOperator" def getNetworkOperator(self) -> str: return "310260" def getNetworkCountryIso(self) -> str: return "us" def getNetworkType(self) -> int: if _USE_LINUX: if LinuxNetwork.get_connectivity(): return self.NETWORK_TYPE_IWLAN return self.NETWORK_TYPE_UNKNOWN return self.NETWORK_TYPE_LTE def getPhoneType(self) -> int: if _USE_LINUX: return self.PHONE_TYPE_NONE return self.PHONE_TYPE_GSM def getDataNetworkType(self) -> int: return self.NETWORK_TYPE_LTE def getVoiceNetworkType(self) -> int: return self.NETWORK_TYPE_LTE def getSimOperator(self) -> str: if _USE_LINUX: return "" return "310260" def getSimOperatorName(self) -> str: return "MockSIM" def getSimCountryIso(self) -> str: return "us" def getSimSerialNumber(self) -> Optional[str]: if _USE_LINUX: return "" return "89014103211118510720" def getSubscriberId(self) -> Optional[str]: if _USE_LINUX: return "" return "310260123456789" def getDeviceId(self) -> Optional[str]: if _USE_LINUX: return LinuxNetwork.get_mac_address() or None return "000000000000000" def getDeviceSoftwareVersion(self) -> Optional[str]: if _USE_LINUX: info = LinuxProcess.get_system_info() return info.get("kernel", "") return "00.00.00.00" def getLine1Number(self) -> Optional[str]: if _USE_LINUX: return "" return "15551234567" def getGroupIdLevel1(self) -> Optional[str]: return "" def getIccAuthentication(self, app_type: int, aid: str, data: bytes) -> Optional[bytes]: return None def getVoiceMailNumber(self) -> Optional[str]: return "15551234567" def getVoiceMailAlphaTag(self) -> str: return "Voicemail" def isNetworkRoaming(self) -> bool: return False def hasIccCard(self) -> bool: return True def getSimState(self) -> int: return self.SIM_STATE_READY def getCellLocation(self) -> Any: # 桌面无基站,Linux 下返回 None if _USE_LINUX: return None return None def getAllCellInfo(self) -> Optional[List[CellInfo]]: return [] def getMmsUserAgent(self) -> str: return "Android-Mms/1.0" def getMmsUAProfUrl(self) -> str: return "http://www.example.com/uaprof.xml" def listen(self, listener: PhoneStateListener, events: int): pass def getDataState(self) -> int: return self.DATA_CONNECTED def getDataActivity(self) -> int: return 0 # DATA_ACTIVITY_NONE def getCallState(self) -> int: return self.CALL_STATE_IDLE def toString(self) -> str: return "TelephonyManager()" # ═══════════════════════════════════════════════════════════════ # __all__ # ═══════════════════════════════════════════════════════════════ __all__ = [ "TelephonyManager", "CellInfo", "CellInfoGsm", "CellInfoCdma", "CellInfoLte", "CellInfoWcdma", "CellInfoNr", "CellIdentityGsm", "CellIdentityCdma", "CellIdentityLte", "CellIdentityWcdma", "CellIdentityNr", "CellSignalStrengthGsm", "CellSignalStrengthCdma", "CellSignalStrengthLte", "CellSignalStrengthWcdma", "CellSignalStrengthNr", "PhoneStateListener", "PhoneNumberUtils", "ServiceState", "SignalStrength", "SmsManager", ]