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,476 @@
|
||||
"""
|
||||
Android Media Transfer Protocol API — MtpDevice, MtpStorageInfo, MtpObjectInfo, MtpConstants
|
||||
方法签名完全对齐 Android SDK
|
||||
"""
|
||||
|
||||
import os as _os
|
||||
import sys
|
||||
import time
|
||||
from datetime import datetime
|
||||
from typing import Any, Dict, List, Optional, Set, Tuple, Callable, BinaryIO
|
||||
|
||||
from .._core import Stub, AndroidOnlyError
|
||||
from ..java.lang import RuntimeException
|
||||
|
||||
|
||||
IllegalArgumentException = type("IllegalArgumentException", (RuntimeException,), {})
|
||||
|
||||
__all__ = [
|
||||
"MtpDevice",
|
||||
"MtpStorageInfo",
|
||||
"MtpObjectInfo",
|
||||
"MtpConstants",
|
||||
"MtpPropertyGroup",
|
||||
"MtpDeviceInfo",
|
||||
"MtpStorage",
|
||||
]
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
# MtpConstants — 50+ 格式常量
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
|
||||
class MtpConstants(Stub):
|
||||
"""MTP 协议常量"""
|
||||
|
||||
# --- 格式常量 ---
|
||||
FORMAT_UNDEFINED = 0x3000
|
||||
FORMAT_ASSOCIATION = 0x3001
|
||||
FORMAT_SCRIPT = 0x3002
|
||||
FORMAT_EXECUTABLE = 0x3003
|
||||
FORMAT_TEXT = 0x3004
|
||||
FORMAT_HTML = 0x3005
|
||||
FORMAT_DPOF = 0x3006
|
||||
FORMAT_AIFF = 0x3007
|
||||
FORMAT_WAV = 0x3008
|
||||
FORMAT_MP3 = 0x3009
|
||||
FORMAT_AVI = 0x300A
|
||||
FORMAT_MPEG = 0x300B
|
||||
FORMAT_ASF = 0x300C
|
||||
FORMAT_DEF = 0x300D
|
||||
FORMAT_EXIF_JPEG = 0x3801
|
||||
FORMAT_TIFF_EP = 0x3802
|
||||
FORMAT_FLASHPIX = 0x3803
|
||||
FORMAT_BMP = 0x3804
|
||||
FORMAT_CIFF = 0x3805
|
||||
FORMAT_GIF = 0x3807
|
||||
FORMAT_JFIF = 0x3808
|
||||
FORMAT_PCD = 0x3809
|
||||
FORMAT_PICT = 0x380A
|
||||
FORMAT_PNG = 0x380B
|
||||
FORMAT_TIFF = 0x380D
|
||||
FORMAT_TIFF_IT = 0x380E
|
||||
FORMAT_JP2 = 0x380F
|
||||
FORMAT_JPX = 0x3810
|
||||
FORMAT_XML = 0x3811
|
||||
FORMAT_FIRMWARE = 0x3802
|
||||
FORMAT_WMA = 0xB901
|
||||
FORMAT_WMV = 0xB980
|
||||
FORMAT_WPL = 0xBA05
|
||||
FORMAT_FLAC = 0xB906
|
||||
FORMAT_OGG = 0xB902
|
||||
FORMAT_AAC = 0xB903
|
||||
FORMAT_MP4_CONTAINER = 0xB904
|
||||
FORMAT_MP2 = 0xB905
|
||||
FORMAT_3GP = 0xB907
|
||||
FORMAT_3GP_CONTAINER = 0xB908
|
||||
FORMAT_AVC = 0xB909
|
||||
FORMAT_HEVC = 0xB90A
|
||||
FORMAT_DNG = 0xB90B
|
||||
FORMAT_ARW = 0xB90C
|
||||
FORMAT_CR2 = 0xB90D
|
||||
FORMAT_RAF = 0xB90E
|
||||
FORMAT_NEF = 0xB90F
|
||||
FORMAT_ORF = 0xB910
|
||||
FORMAT_RW2 = 0xB911
|
||||
FORMAT_SRW = 0xB912
|
||||
|
||||
# --- 保护状态 ---
|
||||
PROTECTION_STATUS_NONE = 0
|
||||
PROTECTION_STATUS_READ_ONLY = 0x8001
|
||||
PROTECTION_STATUS_PROTECTED = 0x8002
|
||||
|
||||
# --- 关联类型 ---
|
||||
ASSOCIATION_TYPE_UNDEFINED = 0x0000
|
||||
ASSOCIATION_TYPE_GENERIC_FOLDER = 0x0001
|
||||
|
||||
# --- 属性格式常量 ---
|
||||
PROP_FORMAT_UNDEFINED = 0x0000
|
||||
PROP_FORMAT_STRING = 0xFFFF
|
||||
PROP_FORMAT_UINT8 = 0x0001
|
||||
PROP_FORMAT_UINT16 = 0x0002
|
||||
PROP_FORMAT_UINT32 = 0x0004
|
||||
PROP_FORMAT_UINT64 = 0x0008
|
||||
PROP_FORMAT_INT8 = 0x0009
|
||||
PROP_FORMAT_INT16 = 0x000A
|
||||
PROP_FORMAT_INT32 = 0x000B
|
||||
PROP_FORMAT_INT64 = 0x000C
|
||||
PROP_FORMAT_BOOL = 0x4001
|
||||
PROP_FORMAT_DATE = 0x4002
|
||||
|
||||
# --- 操作码 ---
|
||||
OPERATION_GET_DEVICE_INFO = 0x1001
|
||||
OPERATION_OPEN_SESSION = 0x1002
|
||||
OPERATION_CLOSE_SESSION = 0x1003
|
||||
OPERATION_GET_STORAGE_IDS = 0x1004
|
||||
OPERATION_GET_STORAGE_INFO = 0x1005
|
||||
OPERATION_GET_OBJECT_PROP_VALUE = 0x9802
|
||||
OPERATION_SET_OBJECT_PROP_VALUE = 0x9803
|
||||
OPERATION_GET_OBJECT_INFO = 0x1007
|
||||
OPERATION_GET_OBJECT = 0x1009
|
||||
OPERATION_GET_THUMB = 0x100A
|
||||
OPERATION_DELETE_OBJECT = 0x100B
|
||||
OPERATION_SEND_OBJECT_INFO = 0x100C
|
||||
OPERATION_SEND_OBJECT = 0x100D
|
||||
OPERATION_GET_OBJECT_REFERENCES = 0x1010
|
||||
OPERATION_SET_OBJECT_REFERENCES = 0x1011
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
# MtpDevice
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
|
||||
class MtpDevice(Stub):
|
||||
"""MtpDevice — MTP 设备 (桌面存根)"""
|
||||
|
||||
def __init__(self, device: Any = None):
|
||||
super().__init__()
|
||||
self._device = device
|
||||
self._opened = False
|
||||
|
||||
def open(self) -> bool:
|
||||
"""打开 MTP 设备"""
|
||||
raise AndroidOnlyError("MtpDevice.open() 仅在 Android 设备上可用")
|
||||
|
||||
def close(self):
|
||||
"""关闭 MTP 设备"""
|
||||
self._opened = False
|
||||
|
||||
def getDeviceInfo(self) -> "MtpDeviceInfo":
|
||||
"""获取设备信息"""
|
||||
return MtpDeviceInfo()
|
||||
|
||||
def getDeviceName(self) -> str:
|
||||
"""获取设备名称"""
|
||||
return "MTP Device"
|
||||
|
||||
def getObjectHandles(
|
||||
self, storageId: int, format: int, objectHandle: int
|
||||
) -> List[int]:
|
||||
"""获取对象句柄列表"""
|
||||
return []
|
||||
|
||||
def getObjectInfo(self, objectHandle: int) -> Optional["MtpObjectInfo"]:
|
||||
"""获取对象信息"""
|
||||
return None
|
||||
|
||||
def getObject(self, objectHandle: int, dataSize: int) -> Optional[bytes]:
|
||||
"""获取对象数据"""
|
||||
return None
|
||||
|
||||
def getThumbnail(self, objectHandle: int) -> Optional[bytes]:
|
||||
"""获取缩略图"""
|
||||
return None
|
||||
|
||||
def getStorageIds(self) -> List[int]:
|
||||
"""获取存储 ID 列表"""
|
||||
return [0x00010001]
|
||||
|
||||
def getStorageInfo(self, storageId: int) -> "MtpStorageInfo":
|
||||
"""获取存储信息"""
|
||||
return MtpStorageInfo()
|
||||
|
||||
def importFile(self, objectHandle: int, destPath: str) -> bool:
|
||||
"""导入文件"""
|
||||
raise AndroidOnlyError("MtpDevice.importFile() 仅在 Android 设备上可用")
|
||||
|
||||
def deleteObject(self, objectHandle: int) -> bool:
|
||||
"""删除对象"""
|
||||
raise AndroidOnlyError("MtpDevice.deleteObject() 仅在 Android 设备上可用")
|
||||
|
||||
def getParent(self, objectHandle: int) -> int:
|
||||
"""获取父对象句柄"""
|
||||
return 0xFFFFFFFF
|
||||
|
||||
def getObjectReferences(self, objectHandle: int) -> List[int]:
|
||||
"""获取对象引用列表"""
|
||||
return []
|
||||
|
||||
def setObjectReferences(self, objectHandle: int, references: List[int]) -> bool:
|
||||
"""设置对象引用"""
|
||||
raise AndroidOnlyError("MtpDevice.setObjectReferences() 仅在 Android 设备上可用")
|
||||
|
||||
def sendObject(self, objectHandle: int, data: bytes) -> bool:
|
||||
"""发送对象"""
|
||||
raise AndroidOnlyError("MtpDevice.sendObject() 仅在 Android 设备上可用")
|
||||
|
||||
def sendObjectInfo(
|
||||
self, storageId: int, parent: int, info: "MtpObjectInfo"
|
||||
) -> int:
|
||||
"""发送对象信息"""
|
||||
raise AndroidOnlyError("MtpDevice.sendObjectInfo() 仅在 Android 设备上可用")
|
||||
|
||||
def toString(self) -> str:
|
||||
return f"MtpDevice(name={self.getDeviceName()})"
|
||||
|
||||
def equals(self, other) -> bool:
|
||||
return self is other
|
||||
|
||||
def hashCode(self) -> int:
|
||||
return id(self) & 0x7FFFFFFF
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
# MtpStorageInfo
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
|
||||
class MtpStorageInfo(Stub):
|
||||
"""MtpStorageInfo — MTP 存储信息"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self._storage_id = 0x00010001
|
||||
self._max_capacity = 32 * 1024 * 1024 * 1024 # 32GB
|
||||
self._free_space = 16 * 1024 * 1024 * 1024 # 16GB
|
||||
self._description = "Internal Storage"
|
||||
self._volume_identifier = ""
|
||||
|
||||
def getStorageId(self) -> int:
|
||||
return self._storage_id
|
||||
|
||||
def getMaxCapacity(self) -> int:
|
||||
return self._max_capacity
|
||||
|
||||
def getFreeSpace(self) -> int:
|
||||
return self._free_space
|
||||
|
||||
def getDescription(self) -> str:
|
||||
return self._description
|
||||
|
||||
def getVolumeIdentifier(self) -> str:
|
||||
return self._volume_identifier
|
||||
|
||||
def toString(self) -> str:
|
||||
return (f"MtpStorageInfo(id={self._storage_id}, "
|
||||
f"free={self._free_space}B)")
|
||||
|
||||
def equals(self, other) -> bool:
|
||||
if not isinstance(other, MtpStorageInfo):
|
||||
return False
|
||||
return self._storage_id == other._storage_id
|
||||
|
||||
def hashCode(self) -> int:
|
||||
return self._storage_id & 0x7FFFFFFF
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
# MtpObjectInfo
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
|
||||
class MtpObjectInfo(Stub):
|
||||
"""MtpObjectInfo — MTP 对象信息"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self._object_handle = 0
|
||||
self._storage_id = 0
|
||||
self._format = MtpConstants.FORMAT_UNDEFINED
|
||||
self._protection_status = MtpConstants.PROTECTION_STATUS_NONE
|
||||
self._compressed_size = 0
|
||||
self._thumb_format = MtpConstants.FORMAT_UNDEFINED
|
||||
self._thumb_compressed_size = 0
|
||||
self._thumb_pix_width = 0
|
||||
self._thumb_pix_height = 0
|
||||
self._image_pix_width = 0
|
||||
self._image_pix_height = 0
|
||||
self._image_pix_depth = 0
|
||||
self._parent = 0
|
||||
self._association_desc = 0
|
||||
self._association_type = 0
|
||||
self._sequence_number = 0
|
||||
self._name = ""
|
||||
self._date_created = 0
|
||||
self._date_modified = 0
|
||||
self._keywords = ""
|
||||
|
||||
def getObjectHandle(self) -> int:
|
||||
return self._object_handle
|
||||
|
||||
def getStorageId(self) -> int:
|
||||
return self._storage_id
|
||||
|
||||
def getFormat(self) -> int:
|
||||
return self._format
|
||||
|
||||
def getProtectionStatus(self) -> int:
|
||||
return self._protection_status
|
||||
|
||||
def getCompressedSize(self) -> int:
|
||||
return self._compressed_size
|
||||
|
||||
def getThumbFormat(self) -> int:
|
||||
return self._thumb_format
|
||||
|
||||
def getThumbCompressedSize(self) -> int:
|
||||
return self._thumb_compressed_size
|
||||
|
||||
def getThumbPixWidth(self) -> int:
|
||||
return self._thumb_pix_width
|
||||
|
||||
def getThumbPixHeight(self) -> int:
|
||||
return self._thumb_pix_height
|
||||
|
||||
def getImagePixWidth(self) -> int:
|
||||
return self._image_pix_width
|
||||
|
||||
def getImagePixHeight(self) -> int:
|
||||
return self._image_pix_height
|
||||
|
||||
def getImagePixDepth(self) -> int:
|
||||
return self._image_pix_depth
|
||||
|
||||
def getParent(self) -> int:
|
||||
return self._parent
|
||||
|
||||
def getAssociationDesc(self) -> int:
|
||||
return self._association_desc
|
||||
|
||||
def getAssociationType(self) -> int:
|
||||
return self._association_type
|
||||
|
||||
def getSequenceNumber(self) -> int:
|
||||
return self._sequence_number
|
||||
|
||||
def getName(self) -> str:
|
||||
return self._name
|
||||
|
||||
def getDateCreated(self) -> int:
|
||||
return self._date_created
|
||||
|
||||
def getDateModified(self) -> int:
|
||||
return self._date_modified
|
||||
|
||||
def getKeywords(self) -> str:
|
||||
return self._keywords
|
||||
|
||||
def toString(self) -> str:
|
||||
return f"MtpObjectInfo(name={self._name}, handle={self._object_handle})"
|
||||
|
||||
def equals(self, other) -> bool:
|
||||
if not isinstance(other, MtpObjectInfo):
|
||||
return False
|
||||
return self._object_handle == other._object_handle
|
||||
|
||||
def hashCode(self) -> int:
|
||||
return self._object_handle & 0x7FFFFFFF
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
# MtpPropertyGroup
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
|
||||
class MtpPropertyGroup(Stub):
|
||||
"""MtpPropertyGroup — MTP 属性组"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self._properties: Dict[int, Any] = {}
|
||||
|
||||
def getPropertyValue(self, propertyCode: int) -> Optional[Any]:
|
||||
return self._properties.get(propertyCode)
|
||||
|
||||
def toString(self) -> str:
|
||||
return f"MtpPropertyGroup(properties={len(self._properties)})"
|
||||
|
||||
def equals(self, other) -> bool:
|
||||
return self is other
|
||||
|
||||
def hashCode(self) -> int:
|
||||
return id(self) & 0x7FFFFFFF
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
# MtpDeviceInfo
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
|
||||
class MtpDeviceInfo(Stub):
|
||||
"""MtpDeviceInfo — MTP 设备信息"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self._manufacturer = "Unknown"
|
||||
self._model = "MTP Device"
|
||||
self._device_version = "1.0"
|
||||
self._serial_number = "00000000"
|
||||
self._operations_supported: List[int] = []
|
||||
self._events_supported: List[int] = []
|
||||
self._device_properties_supported: List[int] = []
|
||||
|
||||
def getManufacturer(self) -> str:
|
||||
return self._manufacturer
|
||||
|
||||
def getModel(self) -> str:
|
||||
return self._model
|
||||
|
||||
def getDeviceVersion(self) -> str:
|
||||
return self._device_version
|
||||
|
||||
def getSerialNumber(self) -> str:
|
||||
return self._serial_number
|
||||
|
||||
def getOperationsSupported(self) -> List[int]:
|
||||
return list(self._operations_supported)
|
||||
|
||||
def getEventsSupported(self) -> List[int]:
|
||||
return list(self._events_supported)
|
||||
|
||||
def getDevicePropertySupported(self) -> List[int]:
|
||||
return list(self._device_properties_supported)
|
||||
|
||||
def toString(self) -> str:
|
||||
return f"MtpDeviceInfo(manufacturer={self._manufacturer}, model={self._model})"
|
||||
|
||||
def equals(self, other) -> bool:
|
||||
if not isinstance(other, MtpDeviceInfo):
|
||||
return False
|
||||
return self._serial_number == other._serial_number
|
||||
|
||||
def hashCode(self) -> int:
|
||||
return hash(self._serial_number) & 0x7FFFFFFF
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
# MtpStorage
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
|
||||
class MtpStorage(Stub):
|
||||
"""MtpStorage — MTP 存储"""
|
||||
|
||||
def __init__(self, storageId: int = 0x00010001, path: str = ""):
|
||||
super().__init__()
|
||||
self._storage_id = storageId
|
||||
self._path = path
|
||||
self._description = "Storage"
|
||||
|
||||
def getStorageId(self) -> int:
|
||||
return self._storage_id
|
||||
|
||||
def getPath(self) -> str:
|
||||
return self._path
|
||||
|
||||
def getDescription(self) -> str:
|
||||
return self._description
|
||||
|
||||
def toString(self) -> str:
|
||||
return f"MtpStorage(id={self._storage_id}, path={self._path})"
|
||||
|
||||
def equals(self, other) -> bool:
|
||||
if not isinstance(other, MtpStorage):
|
||||
return False
|
||||
return self._storage_id == other._storage_id
|
||||
|
||||
def hashCode(self) -> int:
|
||||
return self._storage_id & 0x7FFFFFFF
|
||||
Reference in new issue
Block a user