- 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关键字冲突
1545 lines
51 KiB
Python
1545 lines
51 KiB
Python
"""
|
|
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 |