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:
1 parent
8ad62be068
commit
506f9ac725
43 files changed
+16704
-23
No files matched your search
@@ -0,0 +1,175 @@
|
||||
"""
|
||||
Android se 组件 — SecureElement, Session, Channel, Reader, OmapiConnection 等
|
||||
方法签名完全对齐 Android SDK (SecureElement API)
|
||||
"""
|
||||
|
||||
from typing import Any, Callable, Dict, List, Optional
|
||||
|
||||
from .._core import Stub, AndroidOnlyError
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
# SecureElement
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
|
||||
class SecureElement(Stub):
|
||||
"""SecureElement — 安全元件"""
|
||||
|
||||
SERVICE_INTERFACE = "android.se.SECURE_ELEMENT_SERVICE"
|
||||
EXTRA_READER = "android.se.extra.READER"
|
||||
EXTRA_READER_NAME = "android.se.extra.READER_NAME"
|
||||
EXTRA_SLOT_ID = "android.se.extra.SLOT_ID"
|
||||
EXTRA_CONNECT_RESPONSE = "android.se.extra.CONNECT_RESPONSE"
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
# Reader
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
|
||||
class Reader(Stub):
|
||||
"""Reader — 安全元件读取器"""
|
||||
|
||||
def __init__(self, name: str = "eSE"):
|
||||
super().__init__()
|
||||
self._name = name
|
||||
self._sessions: List[Session] = []
|
||||
|
||||
def getName(self) -> str:
|
||||
return self._name
|
||||
|
||||
def openSession(self) -> "Session":
|
||||
session = Session(self)
|
||||
self._sessions.append(session)
|
||||
return session
|
||||
|
||||
def closeSessions(self):
|
||||
for s in self._sessions:
|
||||
s.close()
|
||||
self._sessions.clear()
|
||||
|
||||
def isSecureElementPresent(self) -> bool:
|
||||
return True
|
||||
|
||||
def toString(self) -> str:
|
||||
return f"Reader(name={self._name})"
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
# Session
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
|
||||
class Session(Stub):
|
||||
"""Session — 安全元件会话"""
|
||||
|
||||
def __init__(self, reader: Optional[Reader] = None):
|
||||
super().__init__()
|
||||
self._reader = reader
|
||||
self._channels: List[Channel] = []
|
||||
self._closed = False
|
||||
|
||||
def openLogicalChannel(self, aid: bytes) -> Optional["Channel"]:
|
||||
if self._closed:
|
||||
return None
|
||||
channel = Channel(self, logical=True)
|
||||
self._channels.append(channel)
|
||||
channel._select_response = bytes([0x90, 0x00]) # SW_OK
|
||||
return channel
|
||||
|
||||
def openBasicChannel(self, aid: bytes) -> Optional["Channel"]:
|
||||
if self._closed:
|
||||
return None
|
||||
channel = Channel(self, logical=False)
|
||||
self._channels.append(channel)
|
||||
channel._select_response = bytes([0x90, 0x00]) # SW_OK
|
||||
return channel
|
||||
|
||||
def close(self):
|
||||
for c in self._channels:
|
||||
c.close()
|
||||
self._channels.clear()
|
||||
self._closed = True
|
||||
|
||||
def getSessions(self) -> List["Session"]:
|
||||
return [self]
|
||||
|
||||
def getChannels(self) -> List["Channel"]:
|
||||
return list(self._channels)
|
||||
|
||||
def toString(self) -> str:
|
||||
return f"Session(reader={self._reader}, channels={len(self._channels)})"
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
# Channel
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
|
||||
class Channel(Stub):
|
||||
"""Channel — 安全元件通道"""
|
||||
|
||||
def __init__(self, session: Session, logical: bool = True):
|
||||
super().__init__()
|
||||
self._session = session
|
||||
self._logical = logical
|
||||
self._closed = False
|
||||
self._select_response: Optional[bytes] = None
|
||||
|
||||
def close(self):
|
||||
self._closed = True
|
||||
|
||||
def sendData(self, command: bytes) -> bytes:
|
||||
if self._closed:
|
||||
return bytes([0x6F, 0x00]) # No such EF
|
||||
# Simulate successful APDU response
|
||||
return bytes([0x90, 0x00])
|
||||
|
||||
def getSelectResponse(self) -> Optional[bytes]:
|
||||
return self._select_response
|
||||
|
||||
def getSession(self) -> Session:
|
||||
return self._session
|
||||
|
||||
def isBasicChannel(self) -> bool:
|
||||
return not self._logical
|
||||
|
||||
def isClosed(self) -> bool:
|
||||
return self._closed
|
||||
|
||||
def toString(self) -> str:
|
||||
return f"Channel(logical={self._logical}, closed={self._closed})"
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
# OmapiConnection
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
|
||||
class OmapiConnection(Stub):
|
||||
"""OmapiConnection — OMAPI 连接入口"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
@staticmethod
|
||||
def getInstance(context: Any = None) -> "OmapiConnection":
|
||||
return OmapiConnection()
|
||||
|
||||
def getReaders(self) -> List[Reader]:
|
||||
return [Reader("eSE")]
|
||||
|
||||
def getReader(self, name: str) -> Optional[Reader]:
|
||||
return Reader(name)
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
# __all__
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
|
||||
__all__ = [
|
||||
"SecureElement",
|
||||
"Reader",
|
||||
"Session",
|
||||
"Channel",
|
||||
"OmapiConnection",
|
||||
]
|
||||
Reference in new issue
Block a user