""" Android Telephony IMS 组件 — ImsManager, ImsService, ImsCall, ImsCallSession, MmTelFeature 等 方法签名完全对齐 Android SDK (android.telephony.ims 包) """ from __future__ import annotations import time from typing import Any, Callable, Dict, List, Optional, Set, Tuple from .._core import Stub, AndroidOnlyError from ..java.lang import RuntimeException # ═══════════════════════════════════════════════════════════════ # IMS 常量 # ═══════════════════════════════════════════════════════════════ IMS_SERVICE_CLASS_NONE = 0 IMS_SERVICE_CLASS_VOICE = 1 IMS_SERVICE_CLASS_VIDEO = 2 IMS_SERVICE_CLASS_SMS = 4 IMS_SERVICE_CLASS_UT = 8 IMS_REGISTRATION_STATE_NOT_REGISTERED = 0 IMS_REGISTRATION_STATE_REGISTERING = 1 IMS_REGISTRATION_STATE_REGISTERED = 2 IMS_REGISTRATION_TECH_NONE = 0 IMS_REGISTRATION_TECH_LTE = 1 IMS_REGISTRATION_TECH_IWLAN = 2 IMS_REGISTRATION_TECH_NR = 3 IMS_CALL_STATE_IDLE = 0 IMS_CALL_STATE_ACTIVE = 1 IMS_CALL_STATE_HOLDING = 2 IMS_CALL_STATE_DIALING = 3 IMS_CALL_STATE_ALERTING = 4 IMS_CALL_STATE_INCOMING = 5 IMS_CALL_STATE_WAITING = 6 IMS_CALL_STATE_DISCONNECTED = 7 IMS_CALL_STATE_DISCONNECTING = 8 IMS_CALL_STATE_UNKNOWN = -1 IMS_CALL_STATE_CONFERENCE = 9 IMS_CALL_STATE_REFER = 10 IMS_CALL_STATE_UPDATE = 11 IMS_FAILURE_REASON_UNKNOWN = 0 IMS_FAILURE_REASON_NETWORK = 1 IMS_FAILURE_REASON_SERVER = 2 IMS_FAILURE_REASON_TIMEOUT = 3 IMS_FAILURE_REASON_INTERNAL = 4 IMS_FAILURE_REASON_BUSY = 5 IMS_FAILURE_REASON_NOT_FOUND = 6 IMS_FAILURE_REASON_FORBIDDEN = 7 IMS_FAILURE_REASON_SERVICE_UNAVAILABLE = 8 IMS_FAILURE_REASON_REQUEST_TIMEOUT = 9 IMS_FAILURE_REASON_TEMPORARILY_UNAVAILABLE = 10 IMS_FAILURE_REASON_MEDIA_NO_ANSWER = 11 IMS_FAILURE_REASON_MEDIA_REJECTED = 12 IMS_FAILURE_REASON_MEDIA_CANCELLED = 13 IMS_FAILURE_REASON_MEDIA_INSUFFICIENT_BANDWIDTH = 14 IMS_FAILURE_REASON_CODE_TEMPORARY_FAILURE = 15 IMS_FAILURE_REASON_CODE_CONGESTION = 16 IMS_FAILURE_REASON_CODE_REQUESTED_TERMINATED = 17 IMS_FAILURE_REASON_CODE_BEARER_NOT_AVAILABLE = 18 IMS_FAILURE_REASON_CODE_INSUFFICIENT_RESOURCES = 19 IMS_FAILURE_REASON_CODE_REJECTED = 20 IMS_FAILURE_REASON_CODE_UNSPECIFIED = 21 IMS_MEDIA_TYPE_AUDIO = 1 IMS_MEDIA_TYPE_VIDEO = 2 IMS_MEDIA_TYPE_TEXT = 3 IMS_SERVICE_TYPE_VOLTE = 0 IMS_SERVICE_TYPE_VIDEO = 1 IMS_SERVICE_TYPE_WFC = 2 IMS_SERVICE_TYPE_SMS = 3 IMS_SERVICE_TYPE_UT = 4 # ═══════════════════════════════════════════════════════════════ # ImsReasonInfo # ═══════════════════════════════════════════════════════════════ class ImsReasonInfo(Stub): """ImsReasonInfo — IMS 原因信息""" CODE_USER_TERMINATED = 0 CODE_USER_TERMINATED_BY_REMOTE = 1 CODE_USER_TRIGGERED_END_OF_CALL = 2 CODE_USER_ANSWERED_ELSEWHERE = 3 CODE_USER_IGNORE = 4 CODE_USER_DECLINE = 5 CODE_USER_NOANSWER = 6 CODE_NETWORK_ERROR = 100 CODE_SIP_REDIRECTED = 200 CODE_SIP_BAD_REQUEST = 400 CODE_SIP_FORBIDDEN = 403 CODE_SIP_NOT_FOUND = 404 CODE_SIP_REQUEST_TIMEOUT = 408 CODE_SIP_TEMPORARILY_UNAVAILABLE = 480 CODE_SIP_BUSY = 486 CODE_SIP_REQUEST_TERMINATED = 487 CODE_SIP_SERVER_INTERNAL_ERROR = 500 CODE_SIP_SERVICE_UNAVAILABLE = 503 CODE_SIP_SERVER_TIMEOUT = 504 CODE_SIP_VERSION_NOT_SUPPORTED = 505 CODE_SIP_BUSY_EVERYWHERE = 600 CODE_SIP_DECLINE = 603 CODE_SIP_DOES_NOT_EXIST_ANYWHERE = 604 CODE_SIP_NOT_ACCEPTABLE = 606 CODE_MEDIA_INIT_FAILED = 700 CODE_MEDIA_NO_DATA = 701 CODE_MEDIA_NOT_ACCEPTABLE = 702 CODE_MEDIA_UNSUPPORTED = 703 CODE_MEDIA_SESSION_TERMINATED = 704 CODE_MEDIA_NO_SESSION = 705 CODE_MEDIA_RTP_TIMEOUT = 706 CODE_MEDIA_RTCP_TIMEOUT = 707 CODE_MEDIA_RESOURCE_LIMIT = 708 CODE_MEDIA_INSUFFICIENT_BANDWIDTH = 709 CODE_MEDIA_LATE_MEDIA = 710 CODE_MEDIA_UNKNOWN = 711 CODE_SIP_ALTERNATE_EMERGENCY_CALL = 712 CODE_LOCAL_ILLEGAL_ARGUMENT = 800 CODE_LOCAL_ILLEGAL_STATE = 801 CODE_LOCAL_INTERNAL_ERROR = 802 CODE_LOCAL_IMS_SERVICE_DOWN = 803 CODE_LOCAL_NO_PENDING_CALL = 804 CODE_LOCAL_SERVICE_NOT_RUNNING = 805 CODE_LOCAL_SERVICE_NOT_READY = 806 CODE_LOCAL_SERVICE_TERMINATED = 807 CODE_LOCAL_CALL_CS_RETRY_REQUIRED = 808 EXTRA_CODE_CALL_RETRY_NEEDED = 1000 EXTRA_CODE_CALL_RETRY_SIP = 1001 EXTRA_CODE_CALL_RETRY_NORMAL = 1002 EXTRA_CODE_CALL_RETRY_EMERGENCY = 1003 def __init__(self, code: int = CODE_USER_TERMINATED, extra_code: int = 0, message: str = ""): super().__init__() self._code = code self._extra_code = extra_code self._message = message def getCode(self) -> int: return self._code def getExtraCode(self) -> int: return self._extra_code def getExtraMessage(self) -> str: return self._message def toString(self) -> str: return f"ImsReasonInfo(code={self._code}, extra={self._extra_code}, msg={self._message})" # ═══════════════════════════════════════════════════════════════ # ImsCallProfile # ═══════════════════════════════════════════════════════════════ class ImsCallProfile(Stub): """ImsCallProfile — IMS 呼叫配置文件""" SERVICE_TYPE_NORMAL = 0 SERVICE_TYPE_EMERGENCY = 1 CALL_TYPE_VOICE = 1 CALL_TYPE_VT = 2 CALL_TYPE_VT_TX = 3 CALL_TYPE_VT_RX = 4 CALL_TYPE_VT_NODIR = 5 CALL_TYPE_SMS = 6 DIALSTRING_NORMAL = 0 DIALSTRING_SS_CONF = 1 DIALSTRING_USSD = 2 EXTRA_CALL_MODE_CHANGEABLE = "call_mode_changeable" EXTRA_CONFERENCE_ALLOWED = "conference_allowed" EXTRA_ADDITIONAL_CALL_INFO = "additional_call_info" EXTRA_CHILD_NETWORK_TYPE = "child_network_type" EXTRA_CNAPN = "cnapn" EXTRA_DIALSTRING = "dialstring" EXTRA_OI = "oi" EXTRA_OIR = "oir" EXTRA_CNAP = "cnap" EXTRA_USSD = "ussd" EXTRA_CALL_RAT = "call_rat" EXTRA_CALL_RAT_TYPE = "call_rat_type" EXTRA_RTT_STATE = "rtt_state" EXTRA_PRIORITY = "priority" EXTRA_PEER_CONNECTION_TYPE = "peer_connection_type" EXTRA_IS_PULL = "is_pull" EXTRA_ADD_IMS_HANDOVER = "add_ims_handover" def __init__(self, service_type: int = SERVICE_TYPE_NORMAL, call_type: int = CALL_TYPE_VOICE): super().__init__() self._service_type = service_type self._call_type = call_type self._media_profiles: List[ImsStreamMediaProfile] = [] self._extras: Dict[str, Any] = {} def getServiceType(self) -> int: return self._service_type def setServiceType(self, service_type: int): self._service_type = service_type def getCallType(self) -> int: return self._call_type def setCallType(self, call_type: int): self._call_type = call_type def getMediaProfile(self) -> Optional[ImsStreamMediaProfile]: if self._media_profiles: return self._media_profiles[0] return None def setMediaProfile(self, profile: ImsStreamMediaProfile): if self._media_profiles: self._media_profiles[0] = profile else: self._media_profiles.append(profile) def getMediaProfiles(self) -> List[ImsStreamMediaProfile]: return list(self._media_profiles) def setMediaProfiles(self, profiles: List[ImsStreamMediaProfile]): self._media_profiles = list(profiles) def getExtra(self, key: str) -> Optional[Any]: return self._extras.get(key) def setExtra(self, key: str, value: Any): self._extras[key] = value def toString(self) -> str: return f"ImsCallProfile(type={self._call_type}, service={self._service_type})" # ═══════════════════════════════════════════════════════════════ # ImsStreamMediaProfile # ═══════════════════════════════════════════════════════════════ class ImsStreamMediaProfile(Stub): """ImsStreamMediaProfile — IMS 流媒体配置文件""" DIRECTION_INVALID = -1 DIRECTION_INACTIVE = 0 DIRECTION_RECEIVE = 1 DIRECTION_SEND = 2 DIRECTION_SEND_RECEIVE = 3 RTT_MODE_DISABLED = 0 RTT_MODE_ENABLED = 1 RTT_MODE_FULL = 2 AUDIO_QUALITY_NONE = 0 AUDIO_QUALITY_AMR = 1 AUDIO_QUALITY_AMR_WB = 2 AUDIO_QUALITY_QCELP13K = 3 AUDIO_QUALITY_EVRC = 4 AUDIO_QUALITY_EVRC_B = 5 AUDIO_QUALITY_EVRC_WB = 6 AUDIO_QUALITY_EVRC_NW = 7 AUDIO_QUALITY_GSM_EFR = 8 AUDIO_QUALITY_GSM_FR = 9 AUDIO_QUALITY_GSM_HR = 10 AUDIO_QUALITY_G722 = 11 AUDIO_QUALITY_G723 = 12 AUDIO_QUALITY_G711 = 13 AUDIO_QUALITY_G729 = 14 AUDIO_QUALITY_EVS_NB = 15 AUDIO_QUALITY_EVS_WB = 16 AUDIO_QUALITY_EVS_SWB = 17 AUDIO_QUALITY_EVS_FB = 18 VIDEO_QUALITY_NONE = 0 VIDEO_QUALITY_QCIF = 1 VIDEO_QUALITY_QVGA = 2 VIDEO_QUALITY_CIF = 3 VIDEO_QUALITY_VGA = 4 VIDEO_QUALITY_720P = 5 VIDEO_QUALITY_1080P = 6 VIDEO_QUALITY_4K = 7 def __init__(self): super().__init__() self._audio_quality = ImsStreamMediaProfile.AUDIO_QUALITY_NONE self._video_quality = ImsStreamMediaProfile.VIDEO_QUALITY_NONE self._audio_direction = ImsStreamMediaProfile.DIRECTION_INVALID self._video_direction = ImsStreamMediaProfile.DIRECTION_INVALID self._rtt_mode = ImsStreamMediaProfile.RTT_MODE_DISABLED self._audio_codec: str = "" self._video_codec: str = "" self._audio_bitrate: int = 0 self._video_bitrate: int = 0 self._audio_sample_rate: int = 0 def getAudioQuality(self) -> int: return self._audio_quality def setAudioQuality(self, quality: int): self._audio_quality = quality def getVideoQuality(self) -> int: return self._video_quality def setVideoQuality(self, quality: int): self._video_quality = quality def getAudioDirection(self) -> int: return self._audio_direction def setAudioDirection(self, direction: int): self._audio_direction = direction def getVideoDirection(self) -> int: return self._video_direction def setVideoDirection(self, direction: int): self._video_direction = direction def getRttMode(self) -> int: return self._rtt_mode def setRttMode(self, mode: int): self._rtt_mode = mode def getAudioCodec(self) -> str: return self._audio_codec def setAudioCodec(self, codec: str): self._audio_codec = codec def getVideoCodec(self) -> str: return self._video_codec def setVideoCodec(self, codec: str): self._video_codec = codec def isRttCall(self) -> bool: return self._rtt_mode != ImsStreamMediaProfile.RTT_MODE_DISABLED def toString(self) -> str: return f"ImsStreamMediaProfile(audio={self._audio_quality}, video={self._video_quality})" # ═══════════════════════════════════════════════════════════════ # ImsCallSession # ═══════════════════════════════════════════════════════════════ class ImsCallSession(Stub): """ImsCallSession — IMS 呼叫会话""" STATE_IDLE = 0 STATE_NEGOTIATION = 1 STATE_ESTABLISHING = 2 STATE_ESTABLISHED = 3 STATE_TERMINATING = 4 STATE_TERMINATED = 5 STATE_MODIFYING = 6 STATE_HOLDING = 7 STATE_RESUMING = 8 STATE_TRANSFERRING = 9 STATE_CONFERENCE = 10 STATE_REFER = 11 STATE_UPDATE = 12 class Listener(Stub): """ImsCallSession.Listener — 呼叫会话监听器""" def onCallStateChanged(self, session: ImsCallSession, state: int): pass def onCallProfileChanged(self, session: ImsCallSession, profile: ImsCallProfile): pass def onCallQualityChanged(self, session: ImsCallSession, quality: int, video_quality: int): pass def onCallSessionHeld(self, session: ImsCallSession, held: bool): pass def onCallSessionHoldFailed(self, session: ImsCallSession, reason: ImsReasonInfo): pass def onCallSessionHoldReceived(self, session: ImsCallSession, profile: ImsCallProfile): pass def onCallSessionResumeFailed(self, session: ImsCallSession, reason: ImsReasonInfo): pass def onCallSessionResumeReceived(self, session: ImsCallSession, profile: ImsCallProfile): pass def onCallSessionMergeStarted(self, session: ImsCallSession, new_session: ImsCallSession, profile: ImsCallProfile): pass def onCallSessionMergeComplete(self, session: ImsCallSession): pass def onCallSessionMergeFailed(self, session: ImsCallSession, reason: ImsReasonInfo): pass def onCallSessionUpdated(self, session: ImsCallSession, profile: ImsCallProfile): pass def onCallSessionUpdateFailed(self, session: ImsCallSession, reason: ImsReasonInfo): pass def onCallSessionUpdateReceived(self, session: ImsCallSession, profile: ImsCallProfile): pass def onCallSessionTtyModeReceived(self, session: ImsCallSession, mode: int): pass def onCallSessionHandover(self, session: ImsCallSession, src_tech: int, target_tech: int, reason: ImsReasonInfo): pass def onCallSessionHandoverFailed(self, session: ImsCallSession, src_tech: int, target_tech: int, reason: ImsReasonInfo): pass def onCallSessionMayHandover(self, session: ImsCallSession, src_tech: int, target_tech: int): pass def onCallSessionDisconnected(self, session: ImsCallSession, reason: ImsReasonInfo): pass def onCallSessionInitiated(self, session: ImsCallSession, profile: ImsCallProfile): pass def onCallSessionRttModifyRequestReceived(self, session: ImsCallSession, profile: ImsCallProfile): pass def onCallSessionRttModifyResponseReceived(self, session: ImsCallSession, status: int): pass def onCallSessionRttMessageReceived(self, session: ImsCallSession, message: str): pass def onCallSessionMultipartyStateChanged(self, session: ImsCallSession, is_multi_party: bool): pass def onCallSessionConferenceStateUpdated(self, session: ImsCallSession, state: Any): pass def onCallSessionTerminated(self, session: ImsCallSession, reason: ImsReasonInfo): pass def __init__(self, context: Any = None, profile: ImsCallProfile = None): super().__init__() self._context = context self._profile = profile or ImsCallProfile() self._state = ImsCallSession.STATE_IDLE self._listener: Optional[ImsCallSession.Listener] = None self._call_id: str = "" self._callee: str = "" self._is_multiparty: bool = False self._media_profile: Optional[ImsStreamMediaProfile] = None def setListener(self, listener: ImsCallSession.Listener): self._listener = listener def getListener(self) -> Optional[ImsCallSession.Listener]: return self._listener def getCallId(self) -> str: return self._call_id def setCallId(self, call_id: str): self._call_id = call_id def getCallee(self) -> str: return self._callee def setCallee(self, callee: str): self._callee = callee def getState(self) -> int: return self._state def setState(self, state: int): self._state = state def getCallProfile(self) -> ImsCallProfile: return self._profile def getLocalCallProfile(self) -> ImsCallProfile: return self._profile def getRemoteCallProfile(self) -> ImsCallProfile: return self._profile def getMediaProfile(self) -> Optional[ImsStreamMediaProfile]: return self._media_profile def isMultiparty(self) -> bool: return self._is_multiparty def start(self, callee: str, profile: ImsCallProfile): self._callee = callee if profile: self._profile = profile self._state = ImsCallSession.STATE_ESTABLISHING self._call_id = f"ims_call_{int(time.time() * 1000)}" if self._listener: self._listener.onCallStateChanged(self, self._state) self._listener.onCallSessionInitiated(self, self._profile) def accept(self, call_type: int, profile: ImsStreamMediaProfile): self._state = ImsCallSession.STATE_ESTABLISHED self._media_profile = profile if self._listener: self._listener.onCallStateChanged(self, self._state) self._listener.onCallProfileChanged(self, self._profile) def reject(self, reason: int): self._state = ImsCallSession.STATE_TERMINATING if self._listener: reason_info = ImsReasonInfo(reason) self._listener.onCallSessionTerminated(self, reason_info) def terminate(self, reason: int = 0): self._state = ImsCallSession.STATE_TERMINATED if self._listener: reason_info = ImsReasonInfo(reason) self._listener.onCallSessionTerminated(self, reason_info) self._listener.onCallStateChanged(self, self._state) def hold(self): self._state = ImsCallSession.STATE_HOLDING if self._listener: self._listener.onCallStateChanged(self, self._state) self._listener.onCallSessionHeld(self, True) def resume(self): self._state = ImsCallSession.STATE_ESTABLISHED if self._listener: self._listener.onCallStateChanged(self, self._state) self._listener.onCallSessionResumeReceived(self, self._profile) def merge(self): if self._listener: self._listener.onCallSessionMergeStarted(self, ImsCallSession(), self._profile) def sendDtmf(self, c: str, result: Any = None): pass def update(self, profile: ImsCallProfile, media_profile: ImsStreamMediaProfile): if self._listener: self._listener.onCallSessionUpdated(self, profile) def sendRttMessage(self, message: str): if self._listener: self._listener.onCallSessionRttMessageReceived(self, message) def sendRttModifyRequest(self, profile: ImsCallProfile): if self._listener: self._listener.onCallSessionRttModifyRequestReceived(self, profile) def sendRttModifyResponse(self, response: int): if self._listener: self._listener.onCallSessionRttModifyResponseReceived(self, response) def close(self): self._state = ImsCallSession.STATE_TERMINATED self._listener = None def toString(self) -> str: return f"ImsCallSession(callId={self._call_id}, state={self._state})" # ═══════════════════════════════════════════════════════════════ # ImsCall # ═══════════════════════════════════════════════════════════════ class ImsCall(Stub): """ImsCall — IMS 呼叫""" class Listener(Stub): """ImsCall.Listener — IMS 呼叫监听器""" def onCallProgressing(self, call: ImsCall, session: ImsCallSession, state: Any): pass def onCallStarted(self, call: ImsCall, session: ImsCallSession): pass def onCallUpdated(self, call: ImsCall, session: ImsCallSession): pass def onCallUpdateFailed(self, call: ImsCall, session: ImsCallSession, reason: ImsReasonInfo): pass def onCallHeld(self, call: ImsCall, session: ImsCallSession): pass def onCallHoldFailed(self, call: ImsCall, session: ImsCallSession, reason: ImsReasonInfo): pass def onCallResumed(self, call: ImsCall, session: ImsCallSession): pass def onCallResumeFailed(self, call: ImsCall, session: ImsCallSession, reason: ImsReasonInfo): pass def onCallMerged(self, call: ImsCall, session: ImsCallSession, merge_session: ImsCallSession): pass def onCallMergeFailed(self, call: ImsCall, session: ImsCallSession, reason: ImsReasonInfo): pass def onCallBusy(self, call: ImsCall, session: ImsCallSession): pass def onCallDisconnected(self, call: ImsCall, session: ImsCallSession, reason: ImsReasonInfo): pass def onCallSuppServiceReceived(self, call: ImsCall, session: ImsCallSession, service: Any): pass def onCallHandover(self, call: ImsCall, session: ImsCallSession, src_tech: int, target_tech: int, reason: ImsReasonInfo): pass def onCallHandoverFailed(self, call: ImsCall, session: ImsCallSession, src_tech: int, target_tech: int, reason: ImsReasonInfo): pass def onCallRttMessageReceived(self, call: ImsCall, message: str): pass def onCallRttModifyRequestReceived(self, call: ImsCall, profile: ImsCallProfile): pass def onCallRttModifyResponseReceived(self, call: ImsCall, status: int): pass def onCallConferenceStateUpdated(self, call: ImsCall, state: Any): pass def onCallSessionEvent(self, call: ImsCall, session: ImsCallSession, event: Any): pass def __init__(self, context: Any = None, profile: ImsCallProfile = None): super().__init__() self._context = context self._profile = profile or ImsCallProfile() self._session: Optional[ImsCallSession] = None self._listener: Optional[ImsCall.Listener] = None self._is_multiparty: bool = False self._state: int = ImsCallSession.STATE_IDLE def setListener(self, listener: ImsCall.Listener): self._listener = listener def getListener(self) -> Optional[ImsCall.Listener]: return self._listener def getSession(self) -> Optional[ImsCallSession]: return self._session def getCallProfile(self) -> ImsCallProfile: return self._profile def getLocalCallProfile(self) -> ImsCallProfile: return self._profile def getRemoteCallProfile(self) -> ImsCallProfile: return self._profile def isMultiparty(self) -> bool: return self._is_multiparty def getState(self) -> int: return self._state def close(self): if self._session: self._session.close() self._session = None self._listener = None def toString(self) -> str: return f"ImsCall(state={self._state}, multi={self._is_multiparty})" # ═══════════════════════════════════════════════════════════════ # ImsConfig # ═══════════════════════════════════════════════════════════════ class ImsConfig(Stub): """ImsConfig — IMS 配置""" CONFIG_START = 0 CONFIG_END = 1 # VoLTE 配置 VO_CONFIG_START = 100 VO_CONFIG_END = 200 # 功能开关 FEATURE_TYPE_VOLTE = 0 FEATURE_TYPE_VIDEO = 1 FEATURE_TYPE_UT = 2 FEATURE_TYPE_UT_OVER_VOLTE = 3 FEATURE_TYPE_UT_OVER_WIFI = 4 FEATURE_TYPE_UNKNOWN = -1 # 操作结果 OPERATION_SUCCESS = 0 OPERATION_FAILED = 1 OPERATION_NOT_SUPPORTED = 2 OPERATION_TIMEOUT = 3 OPERATION_INVALID_PARAM = 4 # VoLTE 设置 VO_SETTING_VOLTE_ENABLED = 101 VO_SETTING_VIDEO_ENABLED = 102 VO_SETTING_WFC_ENABLED = 103 VO_SETTING_WFC_MODE = 104 VO_SETTING_LBO_PCSCF_ADDRESS = 105 VO_SETTING_DOMAIN_NAME = 106 VO_SETTING_SIP_INVITE_TIMEOUT = 107 VO_SETTING_RTT_ENABLED = 108 VO_SETTING_AMR_WB_ENABLED = 109 VO_SETTING_EVS_ENABLED = 110 VO_SETTING_AMR_NB_ENABLED = 111 VO_SETTING_GSM_WB_ENABLED = 112 VO_SETTING_GSM_NB_ENABLED = 113 VO_SETTING_PCSCF_DISCOVERY_ENABLED = 114 VO_SETTING_PCSCF_ADDRESS = 115 VO_SETTING_SIP_SERVER_ADDRESS = 116 VO_SETTING_PUBLIC_USER_IDENTITY = 117 VO_SETTING_PRIVATE_USER_IDENTITY = 118 VO_SETTING_HOME_NETWORK_DOMAIN = 119 VO_SETTING_AM_CODEC = 120 VO_SETTING_VIDEO_CODEC = 121 VO_SETTING_VT_ENABLED = 122 VO_SETTING_LTE_TO_WIFI_HANDOVER_ENABLED = 123 VO_SETTING_WIFI_TO_LTE_HANDOVER_ENABLED = 124 VO_SETTING_LTE_TO_NR_HANDOVER_ENABLED = 125 VO_SETTING_NR_TO_LTE_HANDOVER_ENABLED = 126 class ConfigCallback(Stub): """ImsConfig.ConfigCallback — 配置更改回调""" def onConfigChanged(self, item: int, value: str): pass def onGetFeatureValueResponse(self, feature: int, network: int, value: int, status: int): pass def onSetFeatureValueResponse(self, feature: int, network: int, value: int, status: int): pass def onGetConfigResponse(self, item: int, value: str, status: int): pass def onSetConfigResponse(self, item: int, status: int): pass def __init__(self): super().__init__() self._config: Dict[int, str] = {} self._feature_values: Dict[Tuple[int, int], int] = {} self._callback: Optional[ImsConfig.ConfigCallback] = None def setConfig(self, item: int, value: str) -> int: self._config[item] = value return ImsConfig.OPERATION_SUCCESS def getConfig(self, item: int) -> str: return self._config.get(item, "") def getFeatureValue(self, feature: int, network: int) -> int: return self._feature_values.get((feature, network), 0) def setFeatureValue(self, feature: int, network: int, value: int) -> int: self._feature_values[(feature, network)] = value return ImsConfig.OPERATION_SUCCESS def setConfigCallback(self, callback: ConfigCallback): self._callback = callback def getConfigCallback(self) -> Optional[ConfigCallback]: return self._callback def toString(self) -> str: return f"ImsConfig(settings={len(self._config)})" # ═══════════════════════════════════════════════════════════════ # ImsRegistration # ═══════════════════════════════════════════════════════════════ class ImsRegistration(Stub): """ImsRegistration — IMS 注册信息""" def __init__(self): super().__init__() self._registrant_id: int = 0 self._registration_state: int = IMS_REGISTRATION_STATE_NOT_REGISTERED self._registration_technology: int = IMS_REGISTRATION_TECH_NONE self._sip_uri: str = "" self._feature_tags: List[str] = [] self._supported_media_types: List[int] = [] def getRegistrantId(self) -> int: return self._registrant_id def setRegistrantId(self, rid: int): self._registrant_id = rid def getRegistrationState(self) -> int: return self._registration_state def setRegistrationState(self, state: int): self._registration_state = state def getRegistrationTechnology(self) -> int: return self._registration_technology def setRegistrationTechnology(self, tech: int): self._registration_technology = tech def getSipUri(self) -> str: return self._sip_uri def setSipUri(self, uri: str): self._sip_uri = uri def getFeatureTags(self) -> List[str]: return list(self._feature_tags) def setFeatureTags(self, tags: List[str]): self._feature_tags = list(tags) def getSupportedMediaTypes(self) -> List[int]: return list(self._supported_media_types) def setSupportedMediaTypes(self, types: List[int]): self._supported_media_types = list(types) def isRegistered(self) -> bool: return self._registration_state == IMS_REGISTRATION_STATE_REGISTERED def toString(self) -> str: return f"ImsRegistration(state={self._registration_state}, tech={self._registration_technology})" # ═══════════════════════════════════════════════════════════════ # ImsManager # ═══════════════════════════════════════════════════════════════ class ImsManager(Stub): """ImsManager — IMS 管理器""" ACTION_IMS_SERVICE_UP = "android.telephony.ims.action.IMS_SERVICE_UP" ACTION_IMS_SERVICE_DOWN = "android.telephony.ims.action.IMS_SERVICE_DOWN" ACTION_IMS_REGISTRATION_ERROR = "android.telephony.ims.action.IMS_REGISTRATION_ERROR" EXTRA_PHONE_ID = "android.telephony.ims.extra.PHONE_ID" EXTRA_SUBSCRIPTION_ID = "android.telephony.ims.extra.SUBSCRIPTION_ID" def __init__(self, context: Any = None, phone_id: int = 0): super().__init__() self._context = context self._phone_id = phone_id self._registration: Optional[ImsRegistration] = None self._config: Optional[ImsConfig] = None self._mmtel_features: Dict[int, MmTelFeature] = {} self._registration_callbacks: List[ImsRegistrationCallback] = [] @staticmethod def getInstance(context: Any, phone_id: int) -> ImsManager: return ImsManager(context, phone_id) def getImsService(self) -> Optional[ImsService]: return ImsService(self._context) def getConfig(self) -> Optional[ImsConfig]: if self._config is None: self._config = ImsConfig() return self._config def getRegistration(self) -> Optional[ImsRegistration]: return self._registration def setRegistration(self, registration: ImsRegistration): self._registration = registration def getPhoneId(self) -> int: return self._phone_id def getContext(self) -> Any: return self._context def isServiceSupported(self) -> bool: return True def isServiceReady(self) -> bool: return self._registration is not None and self._registration.isRegistered() def getMmTelFeature(self, sub_id: int) -> Optional[MmTelFeature]: return self._mmtel_features.get(sub_id) def createMmTelFeature(self, sub_id: int) -> MmTelFeature: feature = MmTelFeature(self._context, sub_id) self._mmtel_features[sub_id] = feature return feature def addRegistrationCallback(self, callback: ImsRegistrationCallback): if callback not in self._registration_callbacks: self._registration_callbacks.append(callback) def removeRegistrationCallback(self, callback: ImsRegistrationCallback): self._registration_callbacks = [c for c in self._registration_callbacks if c is not callback] def getRegistrationCallbacks(self) -> List[ImsRegistrationCallback]: return list(self._registration_callbacks) def notifyRegistrationChange(self): for cb in self._registration_callbacks: cb.onRegistered(self._registration) def close(self): self._config = None self._registration = None self._registration_callbacks.clear() self._mmtel_features.clear() def toString(self) -> str: return f"ImsManager(phoneId={self._phone_id})" # ═══════════════════════════════════════════════════════════════ # ImsRegistrationCallback # ═══════════════════════════════════════════════════════════════ class ImsRegistrationCallback(Stub): """ImsRegistrationCallback — IMS 注册回调""" def onRegistered(self, registration: ImsRegistration): pass def onRegistering(self, registration: ImsRegistration): pass def onDeregistered(self, registration: ImsRegistration, reason: ImsReasonInfo): pass def onTechnologyChanged(self, registration: ImsRegistration): pass def onSubscriberAssociatedUriChanged(self, uris: List[str]): pass # ═══════════════════════════════════════════════════════════════ # ImsService # ═══════════════════════════════════════════════════════════════ class ImsService(Stub): """ImsService — IMS 服务""" CAPABILITY_TYPE_VOLTE = 0 CAPABILITY_TYPE_VIDEO = 1 CAPABILITY_TYPE_UT = 2 CAPABILITY_TYPE_SMS = 3 CAPABILITY_TYPE_MMTEL = 4 CAPABILITY_TYPE_RCS = 5 def __init__(self, context: Any = None): super().__init__() self._context = context self._features: Dict[int, Any] = {} self._is_ready: bool = False self._capabilities: Set[int] = set() def getContext(self) -> Any: return self._context def isReady(self) -> bool: return self._is_ready def setReady(self, ready: bool): self._is_ready = ready def getCapabilities(self) -> Set[int]: return set(self._capabilities) def setCapabilities(self, caps: Set[int]): self._capabilities = set(caps) def hasCapability(self, capability: int) -> bool: return capability in self._capabilities def addCapability(self, capability: int): self._capabilities.add(capability) def removeCapability(self, capability: int): self._capabilities.discard(capability) def getFeature(self, feature_type: int) -> Optional[Any]: return self._features.get(feature_type) def addFeature(self, feature_type: int, feature: Any): self._features[feature_type] = feature def createCallSession(self, profile: ImsCallProfile) -> Optional[ImsCallSession]: return ImsCallSession(self._context, profile) def close(self): self._features.clear() self._capabilities.clear() self._is_ready = False def toString(self) -> str: return f"ImsService(ready={self._is_ready}, caps={len(self._capabilities)})" # ═══════════════════════════════════════════════════════════════ # MmTelFeature # ═══════════════════════════════════════════════════════════════ class MmTelFeature(Stub): """MmTelFeature — MMTel 功能""" # MMTel 功能类型 MMTEL_CAPABILITY_TYPE_VOICE = 0 MMTEL_CAPABILITY_TYPE_VIDEO = 1 MMTEL_CAPABILITY_TYPE_UT = 2 MMTEL_CAPABILITY_TYPE_SMS = 3 MMTEL_CAPABILITY_TYPE_NONE = 4 # 网络类型 NETWORK_TYPE_LTE = 0 NETWORK_TYPE_IWLAN = 1 NETWORK_TYPE_NR = 2 # 功能可用性 CAPABILITY_TYPE_UNKNOWN = -1 CAPABILITY_TYPE_NONE = 0 CAPABILITY_TYPE_VOICE = 1 CAPABILITY_TYPE_VIDEO = 2 CAPABILITY_TYPE_UT = 4 CAPABILITY_TYPE_SMS = 8 CAPABILITY_TYPE_ALL = 15 class Listener(Stub): """MmTelFeature.Listener — MMTel 功能监听器""" def onIncomingCall(self, call_session: ImsCallSession, call_id: str, extras: Any): pass def onIncomingCallAnswered(self, call_session: ImsCallSession, call_id: str, extras: Any): pass def onRejectedCall(self, call_id: str, reason: ImsReasonInfo): pass def onVoiceMessageCountChanged(self, count: int): pass def __init__(self, context: Any = None, sub_id: int = 0): super().__init__() self._context = context self._sub_id = sub_id self._listener: Optional[MmTelFeature.Listener] = None self._mmtel_capabilities: Set[int] = set() self._is_available: bool = False self._network_type: int = MmTelFeature.NETWORK_TYPE_LTE self._call_sessions: Dict[str, ImsCallSession] = {} def setListener(self, listener: MmTelFeature.Listener): self._listener = listener def getListener(self) -> Optional[MmTelFeature.Listener]: return self._listener def getSubscriptionId(self) -> int: return self._sub_id def isAvailable(self) -> bool: return self._is_available def setAvailable(self, available: bool): self._is_available = available def getNetworkType(self) -> int: return self._network_type def setNetworkType(self, network_type: int): self._network_type = network_type def getMmTelCapabilities(self) -> Set[int]: return set(self._mmtel_capabilities) def setMmTelCapabilities(self, caps: Set[int]): self._mmtel_capabilities = set(caps) def hasCapability(self, capability: int) -> bool: return capability in self._mmtel_capabilities def createCallSession(self, profile: ImsCallProfile) -> ImsCallSession: session = ImsCallSession(self._context, profile) session.setCallId(f"mmtel_call_{len(self._call_sessions)}") self._call_sessions[session.getCallId()] = session return session def endCallSession(self, call_id: str): self._call_sessions.pop(call_id, None) def getCallSessions(self) -> List[ImsCallSession]: return list(self._call_sessions.values()) def toString(self) -> str: return f"MmTelFeature(subId={self._sub_id}, available={self._is_available})" # ═══════════════════════════════════════════════════════════════ # MmTelManager # ═══════════════════════════════════════════════════════════════ class MmTelManager(Stub): """MmTelManager — MMTel 管理器""" CAPABILITY_TYPE_VOICE = 0 CAPABILITY_TYPE_VIDEO = 1 CAPABILITY_TYPE_UT = 2 CAPABILITY_TYPE_SMS = 3 CAPABILITY_TYPE_NONE = 4 WIFI_CALLING_SETTING_ENABLED = 0 WIFI_CALLING_SETTING_DISABLED = 1 WIFI_CALLING_SETTING_UNKNOWN = 2 class CapabilityCallback(Stub): """MmTelManager.CapabilityCallback — 能力回调""" def onCapabilitiesChanged(self, capabilities: Set[int]): pass class RegistrationCallback(Stub): """MmTelManager.RegistrationCallback — 注册回调""" def onRegistered(self, registration: ImsRegistration): pass def onRegistering(self, registration: ImsRegistration): pass def onUnregistered(self, reason: ImsReasonInfo): pass def onTechnologyChanged(self, registration: ImsRegistration): pass def onSubscriberAssociatedUriChanged(self, uris: List[str]): pass def __init__(self, context: Any = None, sub_id: int = 0): super().__init__() self._context = context self._sub_id = sub_id self._mmtel_feature: Optional[MmTelFeature] = None self._capability_callbacks: List[MmTelManager.CapabilityCallback] = [] self._registration_callbacks: List[MmTelManager.RegistrationCallback] = [] @staticmethod def getInstance(context: Any, sub_id: int) -> Optional[MmTelManager]: return MmTelManager(context, sub_id) def getSubscriptionId(self) -> int: return self._sub_id def getMmTelFeature(self) -> Optional[MmTelFeature]: return self._mmtel_feature def setMmTelFeature(self, feature: MmTelFeature): self._mmtel_feature = feature def addCapabilityCallback(self, callback: CapabilityCallback): if callback not in self._capability_callbacks: self._capability_callbacks.append(callback) def removeCapabilityCallback(self, callback: CapabilityCallback): self._capability_callbacks = [c for c in self._capability_callbacks if c is not callback] def addRegistrationCallback(self, callback: RegistrationCallback): if callback not in self._registration_callbacks: self._registration_callbacks.append(callback) def removeRegistrationCallback(self, callback: RegistrationCallback): self._registration_callbacks = [c for c in self._registration_callbacks if c is not callback] def isMmTelCapabilitySupported(self, capability: int, transport_type: int) -> bool: return True def isMmTelCapabilityEnabled(self, capability: int, transport_type: int) -> bool: return False def setMmTelCapabilityEnabled(self, capability: int, transport_type: int, enabled: bool): pass def isAdvancedCallingSettingEnabled(self) -> bool: return False def isVoLteSettingEnabled(self) -> bool: return False def isVtSettingEnabled(self) -> bool: return False def isWiFiCallingSettingEnabled(self) -> bool: return False def setVoLteSettingEnabled(self, enabled: bool): pass def setVtSettingEnabled(self, enabled: bool): pass def setWiFiCallingSettingEnabled(self, enabled: bool): pass def sendRttMessage(self, message: str): pass def sendRttModifyRequest(self, profile: ImsCallProfile): pass def sendRttModifyResponse(self, response: int): pass def toString(self) -> str: return f"MmTelManager(subId={self._sub_id})" # ═══════════════════════════════════════════════════════════════ # ImsSsInfo # ═══════════════════════════════════════════════════════════════ class ImsSsInfo(Stub): """ImsSsInfo — IMS 补充业务信息""" NOT_REGISTERED = 0 DISABLED = 0 ENABLED = 1 REGISTERED = 1 SERVICE_TYPE_CFU = 0 SERVICE_TYPE_CFB = 1 SERVICE_TYPE_CFNRY = 2 SERVICE_TYPE_CFNRC = 3 SERVICE_TYPE_CF_ALL = 4 SERVICE_TYPE_CF_ALL_CONDITIONAL = 5 SERVICE_TYPE_CLIP = 6 SERVICE_TYPE_CLIR = 7 SERVICE_TYPE_COLP = 8 SERVICE_TYPE_COLR = 9 SERVICE_TYPE_CW = 10 SERVICE_TYPE_HOLD = 11 SERVICE_TYPE_ECT = 12 SERVICE_TYPE_BAOC = 13 SERVICE_TYPE_BAOIC = 14 SERVICE_TYPE_BAOIC_EXC_HOME = 15 SERVICE_TYPE_BIC_ROAM = 16 SERVICE_TYPE_CB_ALL = 17 SERVICE_TYPE_CB_ALL_OUTGOING = 18 SERVICE_TYPE_CB_ALL_INCOMING = 19 def __init__(self, status: int = NOT_REGISTERED, provision_status: int = 0): super().__init__() self._status = status self._provision_status = provision_status self._call_forwarding_info: Optional[ImsCallForwardInfo] = None def getStatus(self) -> int: return self._status def setStatus(self, status: int): self._status = status def getProvisionStatus(self) -> int: return self._provision_status def setProvisionStatus(self, status: int): self._provision_status = status def isProvisioned(self) -> bool: return self._provision_status == 1 def isRegistered(self) -> bool: return self._status == ImsSsInfo.REGISTERED def getCallForwardInfo(self) -> Optional[ImsCallForwardInfo]: return self._call_forwarding_info def setCallForwardInfo(self, info: ImsCallForwardInfo): self._call_forwarding_info = info def toString(self) -> str: return f"ImsSsInfo(status={self._status})" # ═══════════════════════════════════════════════════════════════ # ImsCallForwardInfo # ═══════════════════════════════════════════════════════════════ class ImsCallForwardInfo(Stub): """ImsCallForwardInfo — IMS 呼叫前转信息""" CDIV_CF_UNCONDITIONAL = 0 CDIV_CF_BUSY = 1 CDIV_CF_NO_REPLY = 2 CDIV_CF_NOT_REACHABLE = 3 CDIV_CF_ALL = 4 CDIV_CF_ALL_CONDITIONAL = 5 def __init__(self, condition: int = CDIV_CF_UNCONDITIONAL, status: int = 0, number: str = "", time_seconds: int = 20): super().__init__() self._condition = condition self._status = status self._number = number self._time_seconds = time_seconds def getCondition(self) -> int: return self._condition def setCondition(self, condition: int): self._condition = condition def getStatus(self) -> int: return self._status def setStatus(self, status: int): self._status = status def getNumber(self) -> str: return self._number def setNumber(self, number: str): self._number = number def getTimeSeconds(self) -> int: return self._time_seconds def setTimeSeconds(self, seconds: int): self._time_seconds = seconds def toString(self) -> str: return f"ImsCallForwardInfo(condition={self._condition}, number={self._number})" # ═══════════════════════════════════════════════════════════════ # ImsUt # ═══════════════════════════════════════════════════════════════ class ImsUt(Stub): """ImsUt — IMS 补充服务""" OPERATION_SUCCESS = 0 OPERATION_FAILED = 1 OPERATION_NOT_SUPPORTED = 2 OPERATION_TIMEOUT = 3 OPERATION_NETWORK_ERROR = 4 OPERATION_INVALID_PARAM = 5 class Listener(Stub): """ImsUt.Listener — 补充服务监听器""" def onUtConfigurationUpdated(self, result: int): pass def onUtConfigurationUpdateFailed(self, result: int): pass def onUtConfigurationQueried(self, result: int, ss_info: List[ImsSsInfo]): pass def onUtConfigurationQueryFailed(self, result: int): pass def onUtConfigurationCallBarringQueried(self, result: int, ss_info: List[ImsSsInfo]): pass def onUtConfigurationCallForwardQueried(self, result: int, ss_info: List[ImsSsInfo]): pass def onUtConfigurationCallWaitingQueried(self, result: int, ss_info: List[ImsSsInfo]): pass def __init__(self): super().__init__() self._listener: Optional[ImsUt.Listener] = None def setListener(self, listener: ImsUt.Listener): self._listener = listener def getListener(self) -> Optional[ImsUt.Listener]: return self._listener def queryCallBarring(self, cb_type: int): pass def queryCallForward(self, condition: int): pass def queryCallWaiting(self): pass def updateCallBarring(self, cb_type: int, enabled: bool, password: str = "", service_class: int = 0): pass def updateCallForward(self, condition: int, enabled: bool, number: str = "", time_seconds: int = 20): pass def updateCallWaiting(self, enabled: bool, service_class: int = 0): pass def close(self): self._listener = None # ═══════════════════════════════════════════════════════════════ # ImsCallSessionCallback # ═══════════════════════════════════════════════════════════════ class ImsCallSessionCallback(Stub): """ImsCallSessionCallback — IMS 呼叫会话回调""" def onCallStateChanged(self, state: int): pass def onCallProfileChanged(self, profile: ImsCallProfile): pass def onCallQualityChanged(self, quality: int, video_quality: int): pass def onCallSessionHeld(self, held: bool): pass def onCallSessionHoldFailed(self, reason: ImsReasonInfo): pass def onCallSessionResumed(self, resume: bool): pass def onCallSessionResumeFailed(self, reason: ImsReasonInfo): pass def onCallSessionMergeStarted(self, session: ImsCallSession, profile: ImsCallProfile): pass def onCallSessionMergeComplete(self, session: ImsCallSession): pass def onCallSessionMergeFailed(self, reason: ImsReasonInfo): pass def onCallSessionUpdated(self, profile: ImsCallProfile): pass def onCallSessionUpdateFailed(self, reason: ImsReasonInfo): pass def onCallSessionTerminated(self, reason: ImsReasonInfo): pass def onCallSessionInitiated(self, profile: ImsCallProfile): pass def onCallSessionHandover(self, src_tech: int, target_tech: int, reason: ImsReasonInfo): pass def onCallSessionHandoverFailed(self, src_tech: int, target_tech: int, reason: ImsReasonInfo): pass def onCallSessionMayHandover(self, src_tech: int, target_tech: int): pass def onCallSessionRttMessageReceived(self, message: str): pass def onCallSessionRttModifyRequestReceived(self, profile: ImsCallProfile): pass def onCallSessionRttModifyResponseReceived(self, status: int): pass # ═══════════════════════════════════════════════════════════════ # ImsStateCallback # ═══════════════════════════════════════════════════════════════ class ImsStateCallback(Stub): """ImsStateCallback — IMS 状态回调""" def onServiceAvailable(self): pass def onServiceUnavailable(self): pass def onUnavailable(self, reason: int): pass def onConnected(self): pass def onDisconnected(self, reason: int): pass def onResume(self): pass def onSuspend(self): pass def onFeatureStateChanged(self, feature_state: int, network: int): pass def onRegistrationStateChanged(self, state: int): pass