新增模块覆盖: 系统层 (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 行代码
476 lines
15 KiB
Python
476 lines
15 KiB
Python
"""
|
|
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 |