feat: 新增 42 个 Android API 模块

新增模块覆盖:
系统层 (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 行代码
This commit is contained in:
shuiyu1123 committed 2026-06-24 12:00:28 +00:00
1 parent 8ad62be068
commit 506f9ac725
43 files changed
+16704 -23

No files matched your search

+737
View File
@@ -0,0 +1,737 @@
"""
Android Telecom API — TelecomManager, Call, CallAudioState, DisconnectCause, PhoneAccount, Connection
方法签名完全对齐 Android SDK
"""
import sys
import time
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__ = [
"TelecomManager",
"Call",
"CallAudioState",
"DisconnectCause",
"PhoneAccount",
"Connection",
]
# ═══════════════════════════════════════════════════════════════
# TelecomManager
# ═══════════════════════════════════════════════════════════════
class TelecomManager(Stub):
"""TelecomManager — 电信管理器 (桌面存根)"""
ACTION_CHANGE_DEFAULT_DIALER = "android.telecom.action.CHANGE_DEFAULT_DIALER"
ACTION_SHOW_CALL_SETTINGS = "android.telecom.action.SHOW_CALL_SETTINGS"
ACTION_SETTINGS = "android.telecom.action.SETTINGS"
ACTION_SHOW_MISSED_CALLS_NOTIFICATION = "android.telecom.action.SHOW_MISSED_CALLS_NOTIFICATION"
ACTION_CALL_FORWARDING = "android.telecom.action.CALL_FORWARDING"
ACTION_DEFAULT_CALL_SCREENING_APP = "android.telecom.action.DEFAULT_CALL_SCREENING_APP"
ACTION_DEFAULT_DIALER_CHANGED = "android.telecom.action.DEFAULT_DIALER_CHANGED"
ACTION_NEW_UNKNOWN_CALL = "android.telecom.action.NEW_UNKNOWN_CALL"
ACTION_TTY_PREFERRED = "android.telecom.action.TTY_PREFERRED"
ACTION_TTY_ENABLED = "android.telecom.action.TTY_ENABLED"
ACTION_TTY_DISABLED = "android.telecom.action.TTY_DISABLED"
ACTION_CONNECTION_SERVICE_CONFIGURE = "android.telecom.action.CONNECTION_SERVICE_CONFIGURE"
ACTION_CALL_DIAGNOSTIC_STATE_CHANGED = "android.telecom.action.CALL_DIAGNOSTIC_STATE_CHANGED"
DURATION_SHORT = "short"
DURATION_LONG = "long"
EXTRA_CALL_BACK_NUMBER = "android.telecom.extra.CALL_BACK_NUMBER"
EXTRA_CALL_CREATED_TIME_MILLIS = "android.telecom.extra.CALL_CREATED_TIME_MILLIS"
EXTRA_CALL_TECHNOLOGY_TYPE = "android.telecom.extra.CALL_TECHNOLOGY_TYPE"
EXTRA_CALL_NETWORK_TYPE = "android.telecom.extra.CALL_NETWORK_TYPE"
EXTRA_CALL_SUBSTATE = "android.telecom.extra.CALL_SUBSTATE"
EXTRA_CHANGE_DEFAULT_DIALER_PACKAGE_NAME = "android.telecom.extra.CHANGE_DEFAULT_DIALER_PACKAGE_NAME"
EXTRA_CONNECTION_SERVICE = "android.telecom.extra.CONNECTION_SERVICE"
EXTRA_CALL_DISCONNECT_CAUSE = "android.telecom.extra.CALL_DISCONNECT_CAUSE"
EXTRA_DISCONNECT_CAUSE_DESCRIPTION = "android.telecom.extra.DISCONNECT_CAUSE_DESCRIPTION"
EXTRA_PHONE_ACCOUNT_HANDLE = "android.telecom.extra.PHONE_ACCOUNT_HANDLE"
EXTRA_PRIORITY = "android.telecom.extra.PRIORITY"
EXTRA_START_CALL_WITH_VIDEO_STATE = "android.telecom.extra.START_CALL_WITH_VIDEO_STATE"
EXTRA_HANDOVER_FROM = "android.telecom.extra.HANDOVER_FROM"
EXTRA_HANDOVER_TO = "android.telecom.extra.HANDOVER_TO"
EXTRA_IS_HANDOVER = "android.telecom.extra.IS_HANDOVER"
TTY_MODE_OFF = 0
TTY_MODE_FULL = 1
TTY_MODE_HCO = 2
TTY_MODE_VCO = 3
PRESENTATION_ALLOWED = 1
PRESENTATION_RESTRICTED = 2
PRESENTATION_UNKNOWN = 3
PRESENTATION_PAYPHONE = 4
def __init__(self, context: Any = None):
super().__init__()
self._context = context
self._default_dialer = "com.android.dialer"
self._phone_accounts: Dict[str, Any] = {}
def getDefaultDialerPackage(self) -> str:
"""获取默认拨号器包名"""
return self._default_dialer
def getCurrentTtyMode(self) -> int:
"""获取当前 TTY 模式"""
return self.TTY_MODE_OFF
def getCallCapablePhoneAccounts(self) -> List[Any]:
"""获取可通话的电话账户"""
return list(self._phone_accounts.values())
def getPhoneAccount(self, accountHandle: Any) -> Optional[Any]:
"""获取指定电话账户"""
return self._phone_accounts.get(str(accountHandle))
def getPhoneAccountList(self) -> List[Any]:
"""获取电话账户列表"""
return list(self._phone_accounts.values())
def getSimConfig(self, accountHandle: Any) -> Optional[Any]:
"""获取 SIM 配置"""
return None
def registerPhoneAccount(self, account: "PhoneAccount"):
"""注册电话账户"""
self._phone_accounts[str(account.getAccountHandle())] = account
def unregisterPhoneAccount(self, accountHandle: Any):
"""注销电话账户"""
self._phone_accounts.pop(str(accountHandle), None)
def clearPhoneAccounts(self):
"""清除所有电话账户"""
self._phone_accounts.clear()
def clearAccounts(self):
"""清除所有账户"""
self._phone_accounts.clear()
def showInCallScreen(self, showDialpad: bool):
"""显示通话界面"""
pass
def acceptRingingCall(self):
"""接听响铃呼叫"""
pass
def silenceRinger(self):
"""静音铃声"""
pass
def isInCall(self) -> bool:
"""检查是否正在通话"""
return False
def isInManagedCall(self) -> bool:
"""检查是否在托管通话中"""
return False
def addNewIncomingCall(self, phoneAccount: "PhoneAccount", extras: Any = None):
"""添加新的来电"""
pass
def addNewUnknownCall(self, phoneAccount: "PhoneAccount", extras: Any = None):
"""添加新的未知呼叫"""
pass
def handleCreateConferenceComplete(
self, callId: str, response: Any
):
"""处理创建会议完成"""
pass
def transferCall(self, callId: str, targetPhoneAccount: Any):
"""转移呼叫"""
pass
def setUserSelectedOutgoingPhoneAccount(
self, accountHandle: Any
):
"""设置用户选择的呼出电话账户"""
pass
def toString(self) -> str:
return f"TelecomManager@{hex(id(self))}"
def equals(self, other) -> bool:
return self is other
def hashCode(self) -> int:
return id(self) & 0x7FFFFFFF
# ═══════════════════════════════════════════════════════════════
# Call
# ═══════════════════════════════════════════════════════════════
class Call(Stub):
"""Call — 通话 (桌面存根)"""
STATE_ACTIVE = 1
STATE_HOLDING = 2
STATE_DIALING = 3
STATE_RINGING = 4
STATE_CONNECTING = 5
STATE_DISCONNECTED = 6
STATE_DISCONNECTING = 7
STATE_SELECT_PHONE_ACCOUNT = 8
STATE_NEW = 9
STATE_PULLING_CALL = 10
def __init__(self):
super().__init__()
self._state = self.STATE_NEW
self._details: Optional["Call.Details"] = None
self._conferenceable_calls: List["Call"] = []
self._callbacks: List[Callable] = []
self._listeners: List[Callable] = []
def getState(self) -> int:
return self._state
def getDetails(self) -> Optional["Call.Details"]:
return self._details
def getConferenceableCalls(self) -> List["Call"]:
return list(self._conferenceable_calls)
def registerCallback(self, callback: Callable):
if callback not in self._callbacks:
self._callbacks.append(callback)
def unregisterCallback(self, callback: Callable):
if callback in self._callbacks:
self._callbacks.remove(callback)
def addListener(self, listener: Callable):
if listener not in self._listeners:
self._listeners.append(listener)
def removeListener(self, listener: Callable):
if listener in self._listeners:
self._listeners.remove(listener)
def answer(self, videoState: int = 0):
"""接听通话"""
self._state = self.STATE_ACTIVE
def reject(self, rejectWithMessage: bool = False, textMessage: str = ""):
"""拒绝通话"""
self._state = self.STATE_DISCONNECTED
def disconnect(self):
"""挂断通话"""
self._state = self.STATE_DISCONNECTED
def hold(self):
"""保持通话"""
self._state = self.STATE_HOLDING
def unhold(self):
"""取消保持"""
self._state = self.STATE_ACTIVE
def playDtmfTone(self, digit: str):
"""播放 DTMF 音"""
pass
def stopDtmfTone(self):
"""停止 DTMF 音"""
pass
def postDialWait(self, remaining: str):
"""后拨号等待"""
pass
def mergeConference(self):
"""合并会议"""
pass
def splitFromConference(self):
"""从会议分离"""
pass
def sendCallEvent(self, event: str, extras: Any = None):
"""发送通话事件"""
pass
def putExtra(self, key: str, value: Any):
"""设置额外信息"""
pass
# ═══════════════════════════════════════════════════════════
# Details
# ═══════════════════════════════════════════════════════════
class Details(Stub):
"""Call.Details — 通话详细信息"""
DIRECTION_INCOMING = 1
DIRECTION_OUTGOING = 2
CAPABILITY_HOLD = 1
CAPABILITY_SUPPORT_HOLD = 2
CAPABILITY_MERGE_CONFERENCE = 4
CAPABILITY_SWAP_CONFERENCE = 8
CAPABILITY_RESPOND_VIA_TEXT = 16
CAPABILITY_MUTE = 32
CAPABILITY_MANAGE_CONFERENCE = 64
CAPABILITY_SUPPORTS_VT_LOCAL = 128
CAPABILITY_SUPPORTS_VT_REMOTE = 256
CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL = 512
CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL = 1024
CAPABILITY_SUPPORTS_DOWNGRADE_VT_TO_AUDIO = 2048
CAPABILITY_SUPPORTS_VIDEO_CALLING = 4096
CAPABILITY_SUPPORTS_VT_LOCAL_RX = 8192
CAPABILITY_SUPPORTS_VT_LOCAL_TX = 16384
CAPABILITY_SUPPORTS_VT_REMOTE_RX = 32768
CAPABILITY_SUPPORTS_VT_REMOTE_TX = 65536
CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO = 131072
CAPABILITY_CAN_PAUSE_VIDEO = 262144
CAPABILITY_SELF_MANAGED = 524288
CAPABILITY_SUPPORTS_VOIP = 1048576
CAPABILITY_ADD_PARTICIPANT = 2097152
CAPABILITY_CAN_UPGRADE_TO_VIDEO = 4194304
PROPERTY_HIGH_DEF_AUDIO = 1
PROPERTY_WIFI = 2
PROPERTY_EMERGENCY_CALLBACK = 4
PROPERTY_IS_EXTERNAL_CALL = 8
PROPERTY_HAS_CDMA_VOICE_PRIVACY = 16
PROPERTY_SELF_MANAGED = 32
PROPERTY_ASSISTED_DIALING = 64
PROPERTY_NETWORK_IDENTIFIED = 128
PROPERTY_CALL_AUTO_FORWARDED = 256
PROPERTY_CALL_TYPE_UNKNOWN = 512
PROPERTY_IS_VOIP_AUDIO_MODE = 1024
PROPERTY_IS_DOWNGRADED_CALL = 2048
PROPERTY_ENTITLEMENT_CHANNEL = 4096
PROPERTY_PULLED_CALL = 8192
PROPERTY_CROSS_SIM = 16384
PROPERTY_VIDEO_CALL = 32768
PROPERTY_RTT = 65536
def __init__(self):
super().__init__()
self._handle: Any = None
self._gateway_info: Any = None
self._caller_display_name: str = ""
self._call_direction = self.DIRECTION_INCOMING
self._account_handle: Any = None
self._call_capabilities = 0
self._call_properties = 0
self._caller_info: Any = None
self._creation_time_millis = 0
self._connect_time_millis = 0
self._disconnect_cause: Any = None
self._video_state = 0
self._intent_extras: Any = None
self._extras: Any = None
def getHandle(self) -> Optional[Any]:
return self._handle
def getGatewayInfo(self) -> Optional[Any]:
return self._gateway_info
def getCallerDisplayName(self) -> str:
return self._caller_display_name
def getCallDirection(self) -> int:
return self._call_direction
def getAccountHandle(self) -> Optional[Any]:
return self._account_handle
def getCallCapabilities(self) -> int:
return self._call_capabilities
def getCallProperties(self) -> int:
return self._call_properties
def getCallerInfo(self) -> Optional[Any]:
return self._caller_info
def getCreationTimeMillis(self) -> int:
return self._creation_time_millis
def getConnectTimeMillis(self) -> int:
return self._connect_time_millis
def getDisconnectCause(self) -> Optional["DisconnectCause"]:
return self._disconnect_cause
def getVideoState(self) -> int:
return self._video_state
def getIntentExtras(self) -> Optional[Any]:
return self._intent_extras
def getExtras(self) -> Optional[Any]:
return self._extras
def toString(self) -> str:
return f"Call.Details(handle={self._handle})"
def equals(self, other) -> bool:
return self is other
def hashCode(self) -> int:
return id(self) & 0x7FFFFFFF
def toString(self) -> str:
return f"Call(state={self._state})"
def equals(self, other) -> bool:
if not isinstance(other, Call):
return False
return self._state == other._state and self._details == other._details
def hashCode(self) -> int:
return self._state & 0x7FFFFFFF
# ═══════════════════════════════════════════════════════════════
# CallAudioState
# ═══════════════════════════════════════════════════════════════
class CallAudioState(Stub):
"""CallAudioState — 通话音频状态"""
ROUTE_EARPIECE = 1
ROUTE_SPEAKER = 2
ROUTE_BLUETOOTH = 4
ROUTE_WIRED_HEADSET = 8
ROUTE_WIRED_OR_EARPIECE = 9
def __init__(self):
super().__init__()
self._route = self.ROUTE_EARPIECE
self._supported_route_mask = (
self.ROUTE_EARPIECE | self.ROUTE_SPEAKER | self.ROUTE_WIRED_HEADSET
)
def getRoute(self) -> int:
return self._route
def getSupportedRouteMask(self) -> int:
return self._supported_route_mask
def toString(self) -> str:
return f"CallAudioState(route={self._route})"
def equals(self, other) -> bool:
if not isinstance(other, CallAudioState):
return False
return self._route == other._route
def hashCode(self) -> int:
return self._route & 0x7FFFFFFF
# ═══════════════════════════════════════════════════════════════
# DisconnectCause
# ═══════════════════════════════════════════════════════════════
class DisconnectCause(Stub):
"""DisconnectCause — 断连原因"""
LOCAL = 1
REMOTE = 2
BUSY = 3
CANCELED = 4
NO_ANSWER = 5
MISSED = 6
ERROR = 7
REJECTED = 8
NUMBER_UNREACHABLE = 9
RESTRICTED = 10
OTHER = 11
ANSWERED_ELSEWHERE = 12
CALL_PULLED = 13
def __init__(self, causeCode: int = OTHER):
super().__init__()
self._cause_code = causeCode
self._reason: str = ""
self._description: str = ""
def getCode(self) -> int:
return self._cause_code
def getReason(self) -> str:
return self._reason
def getDescription(self) -> str:
return self._description
def toString(self) -> str:
return f"DisconnectCause(code={self._cause_code})"
def equals(self, other) -> bool:
if not isinstance(other, DisconnectCause):
return False
return self._cause_code == other._cause_code
def hashCode(self) -> int:
return self._cause_code & 0x7FFFFFFF
# ═══════════════════════════════════════════════════════════════
# PhoneAccount
# ═══════════════════════════════════════════════════════════════
class PhoneAccount(Stub):
"""PhoneAccount — 电话账户"""
CAP_HOLD = 1
CAP_ADD_CALL = 2
CAP_MULTI_ENDPOINT = 4
CAP_CONFERENCE = 8
CAP_VIDEO_CALLING = 16
CAP_CALL_COMPOSER = 32
CAP_CONNECTION_MANAGER = 64
EXTRA_LOG_SELF_MANAGED_CALLS = "android.telecom.extra.LOG_SELF_MANAGED_CALLS"
EXTRA_ADD_SELF_MANAGED_CALLS = "android.telecom.extra.ADD_SELF_MANAGED_CALLS"
SCREENING_ALLOW = 0
SCREENING_STOP = 1
SCREENING_SILENCE = 2
SCREENING_DISALLOW = 3
SCHEME_SIP = "sip"
SCHEME_TEL = "tel"
SCHEME_VOICEMAIL = "voicemail"
class Builder(Stub):
"""PhoneAccount.Builder — 电话账户构建器"""
def __init__(self, accountHandle: Any, label: str):
super().__init__()
self._account = PhoneAccount()
self._account._account_handle = accountHandle
self._account._label = label
def setCapabilities(self, capabilities: int) -> "PhoneAccount.Builder":
self._account._capabilities = capabilities
return self
def setAddress(self, address: Any) -> "PhoneAccount.Builder":
self._account._address = address
return self
def setSubscriptionAddress(self, address: Any) -> "PhoneAccount.Builder":
self._account._subscription_address = address
return self
def setSupportedUriSchemes(
self, uriSchemes: List[str]
) -> "PhoneAccount.Builder":
self._account._supported_uri_schemes = list(uriSchemes)
return self
def setIcon(self, icon: Any) -> "PhoneAccount.Builder":
self._account._icon = icon
return self
def setHighlightColor(self, color: int) -> "PhoneAccount.Builder":
self._account._highlight_color = color
return self
def setShortDescription(self, description: str) -> "PhoneAccount.Builder":
self._account._short_description = description
return self
def addSupportedUriScheme(
self, uriScheme: str
) -> "PhoneAccount.Builder":
if uriScheme not in self._account._supported_uri_schemes:
self._account._supported_uri_schemes.append(uriScheme)
return self
def setExtras(self, extras: Any) -> "PhoneAccount.Builder":
self._account._extras = extras
return self
def build(self) -> "PhoneAccount":
return self._account
def toString(self) -> str:
return f"PhoneAccount.Builder(label={self._account._label})"
def equals(self, other) -> bool:
return self is other
def hashCode(self) -> int:
return id(self) & 0x7FFFFFFF
def __init__(self):
super().__init__()
self._account_handle: Any = None
self._label: str = ""
self._capabilities: int = 0
self._address: Any = None
self._subscription_address: Any = None
self._supported_uri_schemes: List[str] = [self.SCHEME_TEL]
self._icon: Any = None
self._highlight_color: int = 0
self._short_description: str = ""
self._extras: Any = None
def getAccountHandle(self) -> Optional[Any]:
return self._account_handle
def getLabel(self) -> str:
return self._label
def getCapabilities(self) -> int:
return self._capabilities
def getAddress(self) -> Optional[Any]:
return self._address
def getSubscriptionAddress(self) -> Optional[Any]:
return self._subscription_address
def getSupportedUriSchemes(self) -> List[str]:
return list(self._supported_uri_schemes)
def getIcon(self) -> Optional[Any]:
return self._icon
def getHighlightColor(self) -> int:
return self._highlight_color
def getShortDescription(self) -> str:
return self._short_description
def getExtras(self) -> Optional[Any]:
return self._extras
def toString(self) -> str:
return f"PhoneAccount(label={self._label})"
def equals(self, other) -> bool:
if not isinstance(other, PhoneAccount):
return False
return self._account_handle == other._account_handle
def hashCode(self) -> int:
return hash(str(self._account_handle)) & 0x7FFFFFFF
# ═══════════════════════════════════════════════════════════════
# Connection
# ═══════════════════════════════════════════════════════════════
class Connection(Stub):
"""Connection — 通话连接 (桌面存根)"""
STATE_INITIALIZING = 0
STATE_ACTIVE = 1
STATE_DIALING = 2
STATE_RINGING = 3
STATE_HOLDING = 4
STATE_DISCONNECTED = 5
STATE_PULLING_CALL = 6
CAPABILITY_HOLD = 1
CAPABILITY_SUPPORT_HOLD = 2
CAPABILITY_MERGE_CONFERENCE = 4
CAPABILITY_SWAP_CONFERENCE = 8
CAPABILITY_RESPOND_VIA_TEXT = 16
CAPABILITY_MUTE = 32
CAPABILITY_MANAGE_CONFERENCE = 64
CAPABILITY_SUPPORTS_VT_LOCAL = 128
CAPABILITY_SUPPORTS_VT_REMOTE = 256
CAPABILITY_SUPPORTS_VIDEO_CALLING = 4096
CAPABILITY_SELF_MANAGED = 524288
CAPABILITY_SUPPORTS_VOIP = 1048576
CAPABILITY_ADD_PARTICIPANT = 2097152
PROPERTY_SELF_MANAGED = 32
PROPERTY_IS_VOIP_AUDIO_MODE = 1024
PROPERTY_HIGH_DEF_AUDIO = 1
PROPERTY_WIFI = 2
def __init__(self):
super().__init__()
self._state = self.STATE_INITIALIZING
self._video_state = 0
self._connection_capabilities = 0
self._connection_properties = 0
self._audio_mode_is_voip = False
self._conferenceable_connections: List["Connection"] = []
self._extras: Dict[str, Any] = {}
def setVideoState(self, videoState: int):
self._video_state = videoState
def setActive(self):
self._state = self.STATE_ACTIVE
def setRinging(self):
self._state = self.STATE_RINGING
def setDialing(self):
self._state = self.STATE_DIALING
def setHolding(self):
self._state = self.STATE_HOLDING
def setDisconnected(self, disconnectCause: "DisconnectCause"):
self._state = self.STATE_DISCONNECTED
def setPostDialWait(self, remaining: str):
pass
def setConferenceableConnections(
self, conferenceable: List["Connection"]
):
self._conferenceable_connections = list(conferenceable)
def setAudioModeIsVoip(self, isVoip: bool):
self._audio_mode_is_voip = isVoip
def setConnectionCapabilities(self, capabilities: int):
self._connection_capabilities = capabilities
def setConnectionProperties(self, properties: int):
self._connection_properties = properties
def putExtra(self, key: str, value: Any):
self._extras[key] = value
def onShowIncomingCallUi(self):
pass
def onCallAudioStateChanged(self, audioState: "CallAudioState"):
pass
def destroy(self):
self._state = self.STATE_DISCONNECTED
def onCallFilteringCompleted(self, completion: Any):
pass
def onSilence(self):
pass
def toString(self) -> str:
return f"Connection(state={self._state})"
def equals(self, other) -> bool:
return self is other
def hashCode(self) -> int:
return id(self) & 0x7FFFFFFF