新增模块覆盖: 系统层 (14): system, security, print, opengl, renderscript, transition, test, service_notification, service_controls, service_quicksettings, service_wallpaper, service_autofill, service_dreams, service_vr 应用层 (13): app_admin, app_backup, app_job, app_usage, app_role, app_people, appwidget, companion, credentials, mtp, sip, telecom, speech 硬件媒体层 (15): hardware_display, hardware_fingerprint, hardware_usb, hardware_input, media_audiofx, media_browse, media_session, media_tv, media_midi, media_projection, uwb, se, view_autofill, view_textclassifier, view_translation 总计 94 个模块,75,342 行代码
519 lines
17 KiB
Python
519 lines
17 KiB
Python
"""
|
|
Android SIP API — SipManager, SipProfile, SipSession, SipAudioCall
|
|
(已废弃但存在于 SDK 中)
|
|
方法签名完全对齐 Android SDK
|
|
"""
|
|
|
|
import sys
|
|
from typing import Any, Dict, List, Optional, Set, Tuple, Callable
|
|
|
|
from .._core import Stub, AndroidOnlyError
|
|
from ..java.lang import RuntimeException
|
|
|
|
|
|
IllegalArgumentException = type("IllegalArgumentException", (RuntimeException,), {})
|
|
|
|
__all__ = [
|
|
"SipManager",
|
|
"SipProfile",
|
|
"SipSession",
|
|
"SipAudioCall",
|
|
]
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# SipManager
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class SipManager(Stub):
|
|
"""SipManager — SIP 会话管理器 (桌面存根, 已废弃)"""
|
|
|
|
EXTRA_CALL_ID = "android.sip.extra.CALL_ID"
|
|
EXTRA_OFFER_SD = "android.sip.extra.OFFER_SD"
|
|
EXTRA_PEER_PROFILE = "android.sip.extra.PEER_PROFILE"
|
|
|
|
def __init__(self, context: Any = None):
|
|
super().__init__()
|
|
self._context = context
|
|
self._opened = False
|
|
self._registered = False
|
|
self._session: Optional["SipSession"] = None
|
|
self._listener: Optional[Callable] = None
|
|
|
|
@staticmethod
|
|
def isSipWifiOnly(context: Any) -> bool:
|
|
"""检查 SIP 是否仅限 WiFi"""
|
|
return False
|
|
|
|
@staticmethod
|
|
def isVoipSupported(context: Any) -> bool:
|
|
"""检查是否支持 VoIP"""
|
|
return True
|
|
|
|
@staticmethod
|
|
def isApiSupported(context: Any) -> bool:
|
|
"""检查 SIP API 是否支持"""
|
|
return True
|
|
|
|
@staticmethod
|
|
def newInstance(context: Any) -> "SipManager":
|
|
"""创建新实例"""
|
|
return SipManager(context)
|
|
|
|
def open(self, localProfile: "SipProfile") -> "SipSession":
|
|
"""打开 SIP 会话"""
|
|
self._opened = True
|
|
self._session = SipSession(localProfile)
|
|
return self._session
|
|
|
|
def setRegistrationListener(
|
|
self, localProfileUri: str, listener: "SipSession.Listener"
|
|
):
|
|
"""设置注册监听器"""
|
|
if self._session:
|
|
self._session.setListener(listener)
|
|
|
|
def close(self, localProfileUri: str):
|
|
"""关闭 SIP 会话"""
|
|
self._opened = False
|
|
self._registered = False
|
|
self._session = None
|
|
|
|
def getSessionFor(self, intent: Any) -> Optional["SipSession"]:
|
|
"""获取 Intent 对应的 SIP 会话"""
|
|
return self._session
|
|
|
|
def register(
|
|
self, localProfile: "SipProfile", expiryTime: int, listener: "SipSession.Listener"
|
|
):
|
|
"""注册 SIP"""
|
|
raise AndroidOnlyError("SipManager.register() 仅在 Android 设备上可用")
|
|
|
|
def unregister(
|
|
self, localProfile: "SipProfile", listener: "SipSession.Listener"
|
|
):
|
|
"""注销 SIP"""
|
|
raise AndroidOnlyError("SipManager.unregister() 仅在 Android 设备上可用")
|
|
|
|
def isOpened(self, localProfileUri: str) -> bool:
|
|
"""检查是否已打开"""
|
|
return self._opened
|
|
|
|
def isRegistered(self, localProfileUri: str) -> bool:
|
|
"""检查是否已注册"""
|
|
return self._registered
|
|
|
|
def createSipSessionIfNeeded(self, localProfile: "SipProfile") -> "SipSession":
|
|
"""如有必要则创建 SIP 会话"""
|
|
if self._session is None:
|
|
self._session = SipSession(localProfile)
|
|
return self._session
|
|
|
|
def createSipProfile(self, intent: Any) -> Optional["SipProfile"]:
|
|
"""从 Intent 创建 SIP 配置文件"""
|
|
return None
|
|
|
|
def toString(self) -> str:
|
|
return f"SipManager(opened={self._opened}, registered={self._registered})"
|
|
|
|
def equals(self, other) -> bool:
|
|
return self is other
|
|
|
|
def hashCode(self) -> int:
|
|
return id(self) & 0x7FFFFFFF
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# SipProfile
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class SipProfile(Stub):
|
|
"""SipProfile — SIP 配置文件"""
|
|
|
|
# --- Protocol constants ---
|
|
PROTOCOL_UDP = "UDP"
|
|
PROTOCOL_TCP = "TCP"
|
|
PROTOCOL_TLS = "TLS"
|
|
|
|
class Builder(Stub):
|
|
"""SipProfile.Builder — SIP 配置文件构建器"""
|
|
|
|
def __init__(self, uri: str = ""):
|
|
super().__init__()
|
|
self._profile = SipProfile()
|
|
self._profile._uri = uri
|
|
|
|
def setProfileName(self, name: str) -> "SipProfile.Builder":
|
|
self._profile._profile_name = name
|
|
return self
|
|
|
|
def setUserName(self, userName: str) -> "SipProfile.Builder":
|
|
self._profile._user_name = userName
|
|
return self
|
|
|
|
def setDomain(self, domain: str) -> "SipProfile.Builder":
|
|
self._profile._domain = domain
|
|
return self
|
|
|
|
def setPassword(self, password: str) -> "SipProfile.Builder":
|
|
self._profile._password = password
|
|
return self
|
|
|
|
def setPort(self, port: int) -> "SipProfile.Builder":
|
|
self._profile._port = port
|
|
return self
|
|
|
|
def setProtocol(self, protocol: str) -> "SipProfile.Builder":
|
|
self._profile._protocol = protocol
|
|
return self
|
|
|
|
def setSendKeepAlive(self, enabled: bool) -> "SipProfile.Builder":
|
|
self._profile._send_keep_alive = enabled
|
|
return self
|
|
|
|
def setAutoRegistration(self, enabled: bool) -> "SipProfile.Builder":
|
|
self._profile._auto_registration = enabled
|
|
return self
|
|
|
|
def setDisplayName(self, displayName: str) -> "SipProfile.Builder":
|
|
self._profile._display_name = displayName
|
|
return self
|
|
|
|
def setAuthUserName(self, authUserName: str) -> "SipProfile.Builder":
|
|
self._profile._auth_user_name = authUserName
|
|
return self
|
|
|
|
def build(self) -> "SipProfile":
|
|
return self._profile
|
|
|
|
def toString(self) -> str:
|
|
return f"SipProfile.Builder(name={self._profile._profile_name})"
|
|
|
|
def equals(self, other) -> bool:
|
|
return self is other
|
|
|
|
def hashCode(self) -> int:
|
|
return id(self) & 0x7FFFFFFF
|
|
|
|
def __init__(self):
|
|
super().__init__()
|
|
self._uri = ""
|
|
self._profile_name = ""
|
|
self._user_name = ""
|
|
self._domain = ""
|
|
self._display_name = ""
|
|
self._password = ""
|
|
self._protocol = self.PROTOCOL_UDP
|
|
self._port = 5060
|
|
self._send_keep_alive = False
|
|
self._auto_registration = True
|
|
self._auth_user_name = ""
|
|
|
|
def getProfileName(self) -> str:
|
|
return self._profile_name
|
|
|
|
def getUserName(self) -> str:
|
|
return self._user_name
|
|
|
|
def getDomain(self) -> str:
|
|
return self._domain
|
|
|
|
def getDisplayName(self) -> str:
|
|
return self._display_name
|
|
|
|
def getPassword(self) -> str:
|
|
return self._password
|
|
|
|
def getProtocol(self) -> str:
|
|
return self._protocol
|
|
|
|
def getPort(self) -> int:
|
|
return self._port
|
|
|
|
def getSendKeepAlive(self) -> bool:
|
|
return self._send_keep_alive
|
|
|
|
def isAutoRegistration(self) -> bool:
|
|
return self._auto_registration
|
|
|
|
def getUri(self) -> str:
|
|
return self._uri
|
|
|
|
def toString(self) -> str:
|
|
return (f"SipProfile(name={self._profile_name}, "
|
|
f"user={self._user_name}@{self._domain})")
|
|
|
|
def equals(self, other) -> bool:
|
|
if not isinstance(other, SipProfile):
|
|
return False
|
|
return self._uri == other._uri
|
|
|
|
def hashCode(self) -> int:
|
|
return hash(self._uri) & 0x7FFFFFFF
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# SipSession
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class SipSession(Stub):
|
|
"""SipSession — SIP 会话"""
|
|
|
|
# --- State constants ---
|
|
STATE_READY_TO_CALL = 0
|
|
STATE_INCOMING_CALL = 1
|
|
STATE_INCOMING_CALL_ANSWERING = 2
|
|
STATE_IN_CALL = 3
|
|
STATE_OUTGOING_CALL = 4
|
|
STATE_OUTGOING_CALL_RINGING = 5
|
|
STATE_OUTGOING_CALL_CANCELING = 6
|
|
STATE_PINGING = 7
|
|
STATE_DEREGISTERING = 8
|
|
STATE_CLOSED = 9
|
|
|
|
def __init__(self, profile: "SipProfile" = None):
|
|
super().__init__()
|
|
self._profile = profile
|
|
self._listener: Optional["SipSession.Listener"] = None
|
|
self._state = self.STATE_CLOSED
|
|
self._call_id = ""
|
|
self._peer_profile: Optional[SipProfile] = None
|
|
self._in_call = False
|
|
|
|
def setListener(self, listener: "SipSession.Listener"):
|
|
"""设置会话监听器"""
|
|
self._listener = listener
|
|
|
|
def register(self, duration: int):
|
|
"""注册 SIP"""
|
|
raise AndroidOnlyError("SipSession.register() 仅在 Android 设备上可用")
|
|
|
|
def unregister(self):
|
|
"""注销 SIP"""
|
|
raise AndroidOnlyError("SipSession.unregister() 仅在 Android 设备上可用")
|
|
|
|
def makeAudioCall(
|
|
self, localProfile: "SipProfile", peerProfile: "SipProfile"
|
|
):
|
|
"""发起音频呼叫"""
|
|
raise AndroidOnlyError("SipSession.makeAudioCall() 仅在 Android 设备上可用")
|
|
|
|
def answerCall(self, callId: str, sessionDescription: int):
|
|
"""接听呼叫"""
|
|
raise AndroidOnlyError("SipSession.answerCall() 仅在 Android 设备上可用")
|
|
|
|
def endCall(self):
|
|
"""结束呼叫"""
|
|
raise AndroidOnlyError("SipSession.endCall() 仅在 Android 设备上可用")
|
|
|
|
def changeCall(self, callId: str, sessionDescription: int):
|
|
"""更改呼叫"""
|
|
raise AndroidOnlyError("SipSession.changeCall() 仅在 Android 设备上可用")
|
|
|
|
def getCallId(self) -> str:
|
|
return self._call_id
|
|
|
|
def getPeerProfile(self) -> Optional["SipProfile"]:
|
|
return self._peer_profile
|
|
|
|
def getState(self) -> int:
|
|
return self._state
|
|
|
|
def isInCall(self) -> bool:
|
|
return self._in_call
|
|
|
|
def getLocalProfile(self) -> Optional["SipProfile"]:
|
|
return self._profile
|
|
|
|
# ═══════════════════════════════════════════════════════════
|
|
# Listener
|
|
# ═══════════════════════════════════════════════════════════
|
|
|
|
class Listener(Stub):
|
|
"""SipSession.Listener — SIP 会话监听器"""
|
|
|
|
def __init__(self):
|
|
super().__init__()
|
|
|
|
def onCalling(self, session: "SipSession"):
|
|
"""呼叫中回调"""
|
|
pass
|
|
|
|
def onRinging(self, session: "SipSession", caller: "SipProfile"):
|
|
"""响铃回调"""
|
|
pass
|
|
|
|
def onCallEstablished(self, session: "SipSession", sessionDescription: str):
|
|
"""呼叫建立回调"""
|
|
pass
|
|
|
|
def onCallEnded(self, session: "SipSession"):
|
|
"""呼叫结束回调"""
|
|
pass
|
|
|
|
def onCallBusy(self, session: "SipSession"):
|
|
"""呼叫忙碌回调"""
|
|
pass
|
|
|
|
def onError(self, session: "SipSession", errorCode: int, errorMessage: str):
|
|
"""错误回调"""
|
|
pass
|
|
|
|
def onCallChangeFailed(self, session: "SipSession", errorCode: int, errorMessage: str):
|
|
"""呼叫变更失败回调"""
|
|
pass
|
|
|
|
def onRegistrationDone(self, session: "SipSession", duration: int):
|
|
"""注册成功回调"""
|
|
pass
|
|
|
|
def onRegistrationFailed(
|
|
self, session: "SipSession", errorCode: int, errorMessage: str
|
|
):
|
|
"""注册失败回调"""
|
|
pass
|
|
|
|
def onRegistrationTimeout(self, session: "SipSession"):
|
|
"""注册超时回调"""
|
|
pass
|
|
|
|
def toString(self) -> str:
|
|
return f"SipSession.Listener@{hex(id(self))}"
|
|
|
|
def equals(self, other) -> bool:
|
|
return self is other
|
|
|
|
def hashCode(self) -> int:
|
|
return id(self) & 0x7FFFFFFF
|
|
|
|
def toString(self) -> str:
|
|
return f"SipSession(state={self._state})"
|
|
|
|
def equals(self, other) -> bool:
|
|
return self is other
|
|
|
|
def hashCode(self) -> int:
|
|
return id(self) & 0x7FFFFFFF
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# SipAudioCall
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class SipAudioCall(Stub):
|
|
"""SipAudioCall — SIP 音频呼叫"""
|
|
|
|
def __init__(self, context: Any = None, localProfile: "SipProfile" = None):
|
|
super().__init__()
|
|
self._context = context
|
|
self._local_profile = localProfile
|
|
self._listener: Optional["SipAudioCall.Listener"] = None
|
|
self._muted = False
|
|
self._holding = False
|
|
self._in_call = False
|
|
|
|
def setListener(self, listener: "SipAudioCall.Listener"):
|
|
"""设置音频呼叫监听器"""
|
|
self._listener = listener
|
|
|
|
def startAudio(self):
|
|
"""开始音频"""
|
|
raise AndroidOnlyError("SipAudioCall.startAudio() 仅在 Android 设备上可用")
|
|
|
|
def stopAudio(self):
|
|
"""停止音频"""
|
|
raise AndroidOnlyError("SipAudioCall.stopAudio() 仅在 Android 设备上可用")
|
|
|
|
def close(self):
|
|
"""关闭音频呼叫"""
|
|
self._in_call = False
|
|
self._holding = False
|
|
|
|
def isMuted(self) -> bool:
|
|
return self._muted
|
|
|
|
def toggleMute(self):
|
|
"""切换静音"""
|
|
self._muted = not self._muted
|
|
|
|
def hold(self, hold: int):
|
|
"""保持呼叫"""
|
|
self._holding = (hold != 0)
|
|
|
|
def continueCall(self, sessionDescription: int):
|
|
"""继续呼叫"""
|
|
raise AndroidOnlyError("SipAudioCall.continueCall() 仅在 Android 设备上可用")
|
|
|
|
def makeCall(
|
|
self, localProfile: "SipProfile", peerProfile: "SipProfile", timeout: int
|
|
):
|
|
"""发起呼叫"""
|
|
raise AndroidOnlyError("SipAudioCall.makeCall() 仅在 Android 设备上可用")
|
|
|
|
def answerCall(self, sessionDescription: int):
|
|
"""接听呼叫"""
|
|
raise AndroidOnlyError("SipAudioCall.answerCall() 仅在 Android 设备上可用")
|
|
|
|
def sendDtmf(self, code: int):
|
|
"""发送 DTMF"""
|
|
pass
|
|
|
|
# ═══════════════════════════════════════════════════════════
|
|
# Listener
|
|
# ═══════════════════════════════════════════════════════════
|
|
|
|
class Listener(Stub):
|
|
"""SipAudioCall.Listener — 音频呼叫监听器"""
|
|
|
|
def __init__(self):
|
|
super().__init__()
|
|
|
|
def onReadyToCall(self, call: "SipAudioCall"):
|
|
"""准备呼叫回调"""
|
|
pass
|
|
|
|
def onCallEstablished(self, call: "SipAudioCall", sessionDescription: str):
|
|
"""呼叫建立回调"""
|
|
pass
|
|
|
|
def onCallEnded(self, call: "SipAudioCall"):
|
|
"""呼叫结束回调"""
|
|
pass
|
|
|
|
def onCallHeld(self, call: "SipAudioCall"):
|
|
"""呼叫保持回调"""
|
|
pass
|
|
|
|
def onCallChanged(self, call: "SipAudioCall"):
|
|
"""呼叫变更回调"""
|
|
pass
|
|
|
|
def onError(self, call: "SipAudioCall", errorCode: int, errorMessage: str):
|
|
"""错误回调"""
|
|
pass
|
|
|
|
def onRingingBack(self, call: "SipAudioCall"):
|
|
"""回铃回调"""
|
|
pass
|
|
|
|
def onRinging(self, call: "SipAudioCall", caller: "SipProfile"):
|
|
"""响铃回调"""
|
|
pass
|
|
|
|
def toString(self) -> str:
|
|
return f"SipAudioCall.Listener@{hex(id(self))}"
|
|
|
|
def equals(self, other) -> bool:
|
|
return self is other
|
|
|
|
def hashCode(self) -> int:
|
|
return id(self) & 0x7FFFFFFF
|
|
|
|
def toString(self) -> str:
|
|
return f"SipAudioCall(inCall={self._in_call})"
|
|
|
|
def equals(self, other) -> bool:
|
|
return self is other
|
|
|
|
def hashCode(self) -> int:
|
|
return id(self) & 0x7FFFFFFF |