Files
Android-pyApi/android_pyapi/android/os.py
T
shuiyu1123 39b1da37c9 feat: 全面完善API — 补全核心类方法、存根转真实实现、Exception体系扩展
核心类方法补全:
- Activity: +20方法 (requestWindowFeature, setTitle/getTitle, onKeyDown/onKeyUp, enterPictureInPictureMode, getReferrer, isTaskRoot, navigateUpTo等)
- Fragment: +15方法 (getChildFragmentManager, getParentFragment, requireContext/requireActivity, setMenuVisibility等)
- Intent: +20方法 (getParcelableExtra, setComponent/getComponent, getDataString, getScheme, putExtras等)
- View: +20方法 (setLabelFor, setRotationX/Y, setForeground, setBackgroundTintList等)
- KeyEvent: +7方法 (getCharacters, isSystem, isPrintingKey, isModifierKey, startTracking等)
- Paint: +12方法 (setStrokeCap/Join, getTextBounds, setBlendMode, setLetterSpacing等)
- Notification.Builder: +10方法 (setProgress, setShowWhen, setOnlyAlertOnce, setSound等)

存根转真实实现:
- TrafficStats: 读取 /proc/net/dev 返回真实网络流量
- RecyclerView.Adapter: 观察者模式触发通知
- BaseAdapter: 观察者模式触发通知
- ExifInterface: 使用PIL实现图片翻转/旋转
- Process: 使用os.kill实现进程信号
- FileUtils: 真实文件I/O
- SharedPreferences: 监听器模式
- TelephonyManager.listen: 维护监听器列表
- ScrollView.smoothScrollTo: 更新滚动位置

Exception体系扩展:
- 新增15个Exception/Error类 (ClassNotFoundException, IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchElementException, AssertionError, OutOfMemoryError, StackOverflowError, NoClassDefFoundError, UnsatisfiedLinkError, LinkageError, VerifyError, AbstractMethodError, IncompatibleClassChangeError, ExceptionInInitializerError)

Math/System/Thread/StringBuilder/Integer增强:
- Math: +20方法 (subtractExact, multiplyExact, toIntExact, floorDiv/floorMod, fma等)
- System: getProperties/setProperties/mapLibraryName/getLogger
- Thread: +10方法 (getUncaughtExceptionHandler, getAllStackTraces, getStackTrace, holdLock等)
- StringBuilder: +7方法 (ensureCapacity, trimToSize, setLength, subSequence等)
- Integer: +8静态方法 (compare, compareUnsigned, divideUnsigned, sum, max, min等)

修复:
- app_fragment.py: 使用java.lang.IllegalStateException替代本地定义
- content_intent.py: Intent.setData/getScheme正确从Uri提取scheme
- view_ext.py: KeyEvent继承view.KeyEvent获取所有KEYCODE常量
- __init__.py: 补全Fragment/KeyEvent/MotionEvent/TrafficStats/RecyclerView等导出

统计: 221模块, 3660类, 30826方法, 180217行
2026-06-24 23:46:36 +00:00

2065 lines
62 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
Android OS 组件 — Bundle, Handler, Looper, Message, Build 等
方法签名完全对齐 Android SDK
"""
import asyncio
import functools
import heapq
import os as _os
import sys
import threading
import time as _time
from datetime import datetime
from typing import Any, Callable, Dict, List, Optional, Set, Tuple, TypeVar, Union
from .._core import (
Stub, AndroidOnlyError, android_context,
resolve_android_path, to_android_path,
_sdcard_root, _app_data_dir, _package_name,
HAS_PSUTIL,
)
# Linux 真实实现导入
try:
from .._linux_impl import IS_LINUX, LinuxPower, LinuxProcess, HAS_PSUTIL as _HAS_PSUTIL
_USE_LINUX = IS_LINUX
except ImportError:
_USE_LINUX = False
# ═══════════════════════════════════════════════════════════════
# Build
# ═══════════════════════════════════════════════════════════════
class Build(Stub):
"""Build — 设备信息"""
class VERSION(Stub):
"""版本信息"""
SDK_INT = 34 # Android 14
RELEASE = "14"
INCREMENTAL = "20240301"
CODENAME = "REL"
SECURITY_PATCH = "2024-03-05"
BASE_OS = ""
PREVIEW_SDK_INT = 0
RESOURCES_SDK_INT = 34
MEDIA_PERFORMANCE_CLASS = 0
class VERSION_CODES(Stub):
"""版本代码常量"""
BASE = 1
BASE_1_1 = 2
CUPCAKE = 3
DONUT = 4
ECLAIR = 5
ECLAIR_0_1 = 6
ECLAIR_MR1 = 7
FROYO = 8
GINGERBREAD = 9
GINGERBREAD_MR1 = 10
HONEYCOMB = 11
HONEYCOMB_MR1 = 12
HONEYCOMB_MR2 = 13
ICE_CREAM_SANDWICH = 14
ICE_CREAM_SANDWICH_MR1 = 15
JELLY_BEAN = 16
JELLY_BEAN_MR1 = 17
JELLY_BEAN_MR2 = 18
KITKAT = 19
KITKAT_WATCH = 20
LOLLIPOP = 21
LOLLIPOP_MR1 = 22
M = 23
N = 24
N_MR1 = 25
O = 26
O_MR1 = 27
P = 28
Q = 29
R = 30
S = 31
S_V2 = 32
TIRAMISU = 33
UPSIDE_DOWN_CAKE = 34
VERSION = VERSION()
BOARD = "redfin"
BOOTLOADER = "r7.0-12345"
BRAND = "google"
CPU_ABI = "arm64-v8a"
CPU_ABI2 = ""
DEVICE = "redfin"
DISPLAY = "AP1A.240305.001"
FINGERPRINT = "google/redfin/redfin:14/AP1A.240305.001/12345678:user/release-keys"
HARDWARE = "redfin"
HOST = "build-test-01"
ID = "AP1A.240305.001"
MANUFACTURER = "Google"
MODEL = "Pixel 5"
ODM_SKU = None
PRODUCT = "redfin"
RADIO = ""
SERIAL = "unknown"
SKU = None
SOC_MANUFACTURER = "Qualcomm"
SOC_MODEL = "Snapdragon 765G"
SUPPORTED_32_BIT_ABIS = ["armeabi-v7a", "armeabi"]
SUPPORTED_64_BIT_ABIS = ["arm64-v8a"]
SUPPORTED_ABIS = ["arm64-v8a", "armeabi-v7a", "armeabi"]
TAGS = "release-keys"
TIME = int(_time.time() * 1000)
TYPE = "user"
USER = "build-user"
@staticmethod
def getRadioVersion() -> str:
return ""
@staticmethod
def getSerial() -> str:
return "unknown"
@staticmethod
def getFingerprint() -> str:
return Build.FINGERPRINT
@classmethod
def _populate_from_linux(cls):
"""从 LinuxProcess.get_system_info() 填充真实设备信息"""
try:
info = LinuxProcess.get_system_info() or {}
import platform as _platform
import socket as _socket
hostname = info.get("hostname") or _socket.gethostname()
system = info.get("platform") or _platform.system()
arch = info.get("arch") or _platform.machine()
kernel = info.get("kernel") or _platform.release()
cls.MODEL = hostname
cls.MANUFACTURER = "Linux"
cls.BRAND = system
cls.DEVICE = arch
cls.BOARD = arch
cls.HARDWARE = arch
cls.HOST = hostname
cls.PRODUCT = hostname
cls.DISPLAY = kernel
cls.ID = kernel
# FINGERPRINT: brand/device/device:version/id/build:user/release-keys
cls.FINGERPRINT = (
f"{system}/{hostname}/{arch}:Linux/{kernel}/{hostname}:user/release-keys"
)
# CPU ABI 用架构映射
_abi_map = {
"x86_64": "x86_64", "amd64": "x86_64",
"aarch64": "arm64-v8a", "arm64": "arm64-v8a",
"x86": "x86", "i386": "x86", "i686": "x86",
"armv7l": "armeabi-v7a", "arm": "armeabi-v7a",
}
cls.CPU_ABI = _abi_map.get(arch, arch)
cls.SUPPORTED_ABIS = [cls.CPU_ABI]
cls.SUPPORTED_64_BIT_ABIS = [cls.CPU_ABI] if "64" in cls.CPU_ABI else []
cls.SUPPORTED_32_BIT_ABIS = [cls.CPU_ABI] if "64" not in cls.CPU_ABI else []
except Exception:
pass
# 在 Linux 上用真实系统信息填充 Build
if _USE_LINUX:
Build._populate_from_linux()
# ═══════════════════════════════════════════════════════════════
# SystemClock
# ═══════════════════════════════════════════════════════════════
class SystemClock(Stub):
"""SystemClock — 系统时钟"""
@staticmethod
def elapsedRealtime() -> int:
"""返回自启动以来的毫秒数"""
return int(_time.monotonic() * 1000)
@staticmethod
def elapsedRealtimeNanos() -> int:
return int(_time.monotonic_ns())
@staticmethod
def uptimeMillis() -> int:
"""返回自启动以来(不含深度睡眠)的毫秒数"""
return int(_time.monotonic() * 1000)
@staticmethod
def currentThreadTimeMillis() -> int:
return int(_time.clock_gettime(_time.CLOCK_THREAD_CPUTIME_ID) * 1000)
@staticmethod
def sleep(ms: int):
_time.sleep(ms / 1000.0)
@staticmethod
def setCurrentTimeMillis(millis: int) -> bool:
return False
# ═══════════════════════════════════════════════════════════════
# Environment
# ═══════════════════════════════════════════════════════════════
class Environment(Stub):
"""Environment — 环境目录"""
MEDIA_BAD_REMOVAL = "bad_removal"
MEDIA_CHECKING = "checking"
MEDIA_EJECTING = "ejecting"
MEDIA_MOUNTED = "mounted"
MEDIA_MOUNTED_READ_ONLY = "mounted_ro"
MEDIA_NOFS = "nofs"
MEDIA_REMOVED = "removed"
MEDIA_SHARED = "shared"
MEDIA_UNKNOWN = "unknown"
MEDIA_UNMOUNTABLE = "unmountable"
MEDIA_UNMOUNTED = "unmounted"
DIRECTORY_ALARMS = "Alarms"
DIRECTORY_DCIM = "DCIM"
DIRECTORY_DOCUMENTS = "Documents"
DIRECTORY_DOWNLOADS = "Download"
DIRECTORY_MOVIES = "Movies"
DIRECTORY_MUSIC = "Music"
DIRECTORY_NOTIFICATIONS = "Notifications"
DIRECTORY_PICTURES = "Pictures"
DIRECTORY_PODCASTS = "Podcasts"
DIRECTORY_RINGTONES = "Ringtones"
DIRECTORY_AUDIOBOOKS = "Audiobooks"
DIRECTORY_SCREENSHOTS = "Screenshots"
@staticmethod
def getExternalStorageDirectory() -> str:
return _sdcard_root
@staticmethod
def getExternalStoragePublicDirectory(type_: str) -> str:
path = _os.path.join(_sdcard_root, type_)
_os.makedirs(path, exist_ok=True)
return path
@staticmethod
def getDataDirectory() -> str:
return _os.path.join(_app_data_dir, "data")
@staticmethod
def getDownloadCacheDirectory() -> str:
return _os.path.join(_app_data_dir, "cache", "download")
@staticmethod
def getRootDirectory() -> str:
return _os.path.abspath(_os.sep)
@staticmethod
def getStorageDirectory(user_handle: Any = None) -> str:
return _sdcard_root
@staticmethod
def getExternalStorageState(path: Optional[str] = None) -> str:
return Environment.MEDIA_MOUNTED
@staticmethod
def isExternalStorageRemovable(path: Optional[str] = None) -> bool:
return False
@staticmethod
def isExternalStorageEmulated(path: Optional[str] = None) -> bool:
return True
@staticmethod
def isExternalStorageLegacy(path: Optional[str] = None) -> bool:
return True
# ═══════════════════════════════════════════════════════════════
# Process
# ═══════════════════════════════════════════════════════════════
class Process(Stub):
"""Process — 进程信息"""
# 进程优先级
THREAD_PRIORITY_DEFAULT = 0
THREAD_PRIORITY_LOWEST = -19
THREAD_PRIORITY_BACKGROUND = 10
THREAD_PRIORITY_FOREGROUND = -2
THREAD_PRIORITY_DISPLAY = -4
THREAD_PRIORITY_URGENT_DISPLAY = -8
THREAD_PRIORITY_AUDIO = -16
THREAD_PRIORITY_URGENT_AUDIO = -19
THREAD_PRIORITY_MORE_FAVORABLE = -1
THREAD_PRIORITY_LESS_FAVORABLE = 1
SIGNAL_KILL = 9
SIGNAL_QUIT = 3
SIGNAL_USR1 = 10
SIGNAL_USR2 = 12
@staticmethod
def myTid() -> int:
return threading.get_ident()
@staticmethod
def myUid() -> int:
return 10001
@staticmethod
def myPid() -> int:
return _os.getpid()
@staticmethod
def killProcess(pid):
import signal
try:
_os.kill(pid, signal.SIGKILL)
except (OSError, ProcessLookupError):
pass
@staticmethod
def sendSignal(pid, signal_num):
try:
_os.kill(pid, signal_num)
except (OSError, ProcessLookupError):
pass
@staticmethod
def setThreadPriority(priority: int):
pass
@staticmethod
def setThreadPriority(tid, priority):
try:
_os.setpriority(_os.PRIO_PROCESS, tid, priority)
except (OSError, PermissionError):
pass
@staticmethod
def getElapsedCpuTime() -> int:
return int(_time.clock_gettime(_time.CLOCK_PROCESS_CPUTIME_ID) * 1000)
@staticmethod
def supportsProcesses() -> bool:
return True
# ═══════════════════════════════════════════════════════════════
# BaseBundle / PersistableBundle
# ═══════════════════════════════════════════════════════════════
class BaseBundle(Stub):
"""BaseBundle — Bundle 基类"""
def __init__(self):
super().__init__()
self._map: Dict[str, Any] = {}
self._class_loader = None
def getString(self, key: str, default: Optional[str] = None) -> Optional[str]:
v = self._map.get(key, default)
return str(v) if v is not None else default
def getInt(self, key: str, default: int = 0) -> int:
v = self._map.get(key, default)
try:
return int(v) if v is not None else default
except (ValueError, TypeError):
return default
def getLong(self, key: str, default: int = 0) -> int:
return self.getInt(key, default)
def getFloat(self, key: str, default: float = 0.0) -> float:
v = self._map.get(key, default)
try:
return float(v) if v is not None else default
except (ValueError, TypeError):
return default
def getDouble(self, key: str, default: float = 0.0) -> float:
return self.getFloat(key, default)
def getBoolean(self, key: str, default: bool = False) -> bool:
v = self._map.get(key, default)
if isinstance(v, bool):
return v
if isinstance(v, str):
return v.lower() in ("true", "1", "yes")
return bool(v) if v is not None else default
def getByte(self, key: str, default: int = 0) -> int:
return self.getInt(key, default)
def getChar(self, key: str, default: str = "") -> str:
return str(self._map.get(key, default))
def getShort(self, key: str, default: int = 0) -> int:
return self.getInt(key, default)
def getCharSequence(self, key: str, default: Optional[str] = None) -> Optional[str]:
return self.getString(key, default)
def getSerializable(self, key: str, default: Any = None) -> Any:
return self._map.get(key, default)
def getStringArrayList(self, key: str) -> Optional[List[str]]:
v = self._map.get(key)
if isinstance(v, list):
return [str(x) for x in v]
return None
def getIntegerArrayList(self, key: str) -> Optional[List[int]]:
v = self._map.get(key)
if isinstance(v, list):
return [int(x) for x in v if isinstance(x, (int, float))]
return None
def containsKey(self, key: str) -> bool:
return key in self._map
def isEmpty(self) -> bool:
return len(self._map) == 0
def size(self) -> int:
return len(self._map)
def clear(self):
self._map.clear()
def keySet(self) -> Set[str]:
return set(self._map.keys())
def hasKey(self, key: str) -> bool:
return key in self._map
def toString(self) -> str:
return f"Bundle({self._map})"
def __len__(self) -> int:
return len(self._map)
def __contains__(self, key: str) -> bool:
return key in self._map
def __getitem__(self, key: str):
return self._map[key]
def __setitem__(self, key: str, value: Any):
self._map[key] = value
def __delitem__(self, key: str):
self._map.pop(key, None)
class PersistableBundle(BaseBundle):
"""PersistableBundle — 可持久化的 Bundle"""
def __init__(self, capacity: int = 0):
super().__init__()
def putPersistableBundle(self, key: str, value: "PersistableBundle"):
self._map[key] = value
def getPersistableBundle(self, key: str) -> Optional["PersistableBundle"]:
v = self._map.get(key)
return v if isinstance(v, PersistableBundle) else None
# ═══════════════════════════════════════════════════════════════
# Bundle
# ═══════════════════════════════════════════════════════════════
class Bundle(BaseBundle):
"""Bundle — 键值对数据容器"""
EMPTY: "Bundle" = None # 在类加载后初始化
def __init__(self, capacity: int = 0):
super().__init__()
self._capacity = capacity
def putString(self, key: str, value: Optional[str]):
self._map[key] = value
def putInt(self, key: str, value: int):
self._map[key] = value
def putLong(self, key: str, value: int):
self._map[key] = value
def putFloat(self, key: str, value: float):
self._map[key] = value
def putDouble(self, key: str, value: float):
self._map[key] = value
def putBoolean(self, key: str, value: bool):
self._map[key] = value
def putByte(self, key: str, value: int):
self._map[key] = value
def putChar(self, key: str, value: str):
self._map[key] = value
def putShort(self, key: str, value: int):
self._map[key] = value
def putCharSequence(self, key: str, value: Optional[str]):
self._map[key] = value
def putSerializable(self, key: str, value: Any):
self._map[key] = value
def putParcelable(self, key: str, value: Any):
self._map[key] = value
def putStringArrayList(self, key: str, value: Optional[List[str]]):
self._map[key] = value
def putIntegerArrayList(self, key: str, value: Optional[List[int]]):
self._map[key] = value
# ---- 数组类型 ----
def putIntArray(self, key: str, value: Optional[List[int]]):
self._map[key] = list(value) if value is not None else None
def getIntArray(self, key: str) -> Optional[List[int]]:
v = self._map.get(key)
if isinstance(v, list):
return [int(x) for x in v]
return None
def putStringArray(self, key: str, value: Optional[List[str]]):
self._map[key] = list(value) if value is not None else None
def getStringArray(self, key: str) -> Optional[List[str]]:
v = self._map.get(key)
if isinstance(v, list):
return [str(x) for x in v]
return None
def putLongArray(self, key: str, value: Optional[List[int]]):
self._map[key] = list(value) if value is not None else None
def getLongArray(self, key: str) -> Optional[List[int]]:
v = self._map.get(key)
if isinstance(v, list):
return [int(x) for x in v]
return None
def putBooleanArray(self, key: str, value: Optional[List[bool]]):
self._map[key] = list(value) if value is not None else None
def getBooleanArray(self, key: str) -> Optional[List[bool]]:
v = self._map.get(key)
if isinstance(v, list):
return [bool(x) for x in v]
return None
def putDoubleArray(self, key: str, value: Optional[List[float]]):
self._map[key] = list(value) if value is not None else None
def getDoubleArray(self, key: str) -> Optional[List[float]]:
v = self._map.get(key)
if isinstance(v, list):
return [float(x) for x in v]
return None
def putByteArray(self, key: str, value: Optional[List[int]]):
self._map[key] = list(value) if value is not None else None
def getByteArray(self, key: str) -> Optional[List[int]]:
v = self._map.get(key)
if isinstance(v, list):
return [int(x) & 0xFF for x in v]
return None
def putAll(self, bundle: "Bundle"):
if bundle:
self._map.update(bundle._map)
def getParcelable(self, key: str, default: Any = None) -> Any:
return self._map.get(key, default)
def getBundle(self, key: str) -> Optional["Bundle"]:
v = self._map.get(key)
return v if isinstance(v, Bundle) else None
def putBundle(self, key: str, value: Optional["Bundle"]):
self._map[key] = value
def describeContents(self) -> int:
return 0
def clone(self) -> "Bundle":
b = Bundle()
b._map = dict(self._map)
return b
def deepCopy(self) -> "Bundle":
import copy
b = Bundle()
b._map = copy.deepcopy(self._map)
return b
def filterValues(self):
pass
def getPairValue(self) -> Optional[str]:
return None
def setClassLoader(self, loader: Any):
self._class_loader = loader
def getClassLoader(self) -> Any:
return self._class_loader
@staticmethod
def forPair(key: str, value: str) -> "Bundle":
b = Bundle()
b.putString(key, value)
return b
Bundle.EMPTY = Bundle()
# ═══════════════════════════════════════════════════════════════
# Parcel / Parcelable
# ═══════════════════════════════════════════════════════════════
class Parcelable(Stub):
"""Parcelable 接口"""
CONTENTS_FILE_DESCRIPTOR = "CONTENTS_FILE_DESCRIPTOR"
PARCELABLE_WRITE_RETURN_VALUE = 1
PARCELABLE_ELIDE_DUPLICATES = 2
def describeContents(self) -> int:
return 0
def writeToParcel(self, dest: "Parcel", flags: int):
pass
class Creator:
def createFromParcel(self, source: "Parcel"):
return None
def newArray(self, size: int):
return [None] * size
class ClassLoaderCreator:
def createFromParcel(self, source: "Parcel", loader: Any):
return None
def newArray(self, size: int):
return [None] * size
class Parcel(Stub):
"""Parcel — 序列化数据容器"""
STRING_CREATOR = "STRING_CREATOR"
STRING_LIST_CREATOR = "STRING_LIST_CREATOR"
INT_CREATOR = "INT_CREATOR"
def __init__(self):
super().__init__()
self._data: Dict[str, Any] = {}
self._position = 0
self._size = 0
@staticmethod
def obtain() -> "Parcel":
return Parcel()
def recycle(self):
self._data.clear()
self._position = 0
self._size = 0
def writeInt(self, value: int):
self._data.setdefault("_ints", []).append(value)
self._size += 4
def writeLong(self, value: int):
self._data.setdefault("_longs", []).append(value)
self._size += 8
def writeFloat(self, value: float):
self._data.setdefault("_floats", []).append(value)
self._size += 4
def writeDouble(self, value: float):
self._data.setdefault("_doubles", []).append(value)
self._size += 8
def writeString(self, value: Optional[str]):
strs = self._data.setdefault("_strings", [])
strs.append(value)
self._size += len(value) + 4 if value else 4
def writeBoolean(self, value: bool):
self.writeInt(1 if value else 0)
def writeByte(self, value: int):
self.writeInt(value & 0xFF)
def writeParcelable(self, p: Parcelable, flags: int):
pass
def writeStringArray(self, values: Optional[List[str]]):
self._data["_string_array"] = values
def writeIntArray(self, values: Optional[List[int]]):
self._data["_int_array"] = values
def writeLongArray(self, values: Optional[List[int]]):
self._data["_long_array"] = values
def readInt(self) -> int:
ints = self._data.get("_ints", [])
if ints:
return ints.pop(0)
return 0
def readLong(self) -> int:
longs = self._data.get("_longs", [])
if longs:
return longs.pop(0)
return 0
def readFloat(self) -> float:
floats = self._data.get("_floats", [])
if floats:
return floats.pop(0)
return 0.0
def readDouble(self) -> float:
doubles = self._data.get("_doubles", [])
if doubles:
return doubles.pop(0)
return 0.0
def readString(self) -> Optional[str]:
strs = self._data.get("_strings", [])
if strs:
return strs.pop(0)
return None
def readBoolean(self) -> bool:
return self.readInt() != 0
def readByte(self) -> int:
return self.readInt() & 0xFF
def dataAvail(self) -> int:
return self._size - self._position
def dataPosition(self) -> int:
return self._position
def setDataPosition(self, pos: int):
self._position = pos
def dataSize(self) -> int:
return self._size
def dataCapacity(self) -> int:
return self._size
def setDataCapacity(self, capacity: int):
pass
def appendFrom(self, parcel: "Parcel", offset: int, length: int):
pass
def marshall(self) -> bytes:
import json
return json.dumps(self._data).encode("utf-8")
@staticmethod
def unmarshall(data: bytes) -> "Parcel":
import json
p = Parcel()
try:
p._data = json.loads(data.decode("utf-8"))
except Exception:
pass
return p
def writeValue(self, v: Any):
self._data["_value"] = v
def readValue(self) -> Any:
return self._data.get("_value")
def hasFileDescriptors(self) -> bool:
return False
def toString(self) -> str:
return f"Parcel({self._size} bytes)"
# ═══════════════════════════════════════════════════════════════
# Message
# ═══════════════════════════════════════════════════════════════
class Message(Stub):
"""Message — Handler 消息"""
def __init__(self):
super().__init__()
self.what = 0
self.arg1 = 0
self.arg2 = 0
self.obj: Any = None
self.data: Optional[Bundle] = None
self.replyTo: Optional["Messenger"] = None
self._target: Optional["Handler"] = None
self._callback: Optional[Callable] = None
self.when: int = 0
self._sending = False
@staticmethod
def obtain(handler: Optional["Handler"] = None, what: int = 0) -> "Message":
msg = Message()
if handler:
msg._target = handler
msg.what = what
return msg
def sendToTarget(self):
if self._target:
self._target.sendMessage(self)
def getTarget(self) -> Optional["Handler"]:
return self._target
def setTarget(self, handler: "Handler"):
self._target = handler
@property
def target(self) -> Optional["Handler"]:
return self._target
@target.setter
def target(self, handler: "Handler"):
self._target = handler
def getCallback(self) -> Optional[Callable]:
return self._callback
def copyFrom(self, other: "Message"):
self.what = other.what
self.arg1 = other.arg1
self.arg2 = other.arg2
self.obj = other.obj
self.data = other.data
self.replyTo = other.replyTo
def recycle(self):
self.what = 0
self.arg1 = 0
self.arg2 = 0
self.obj = None
self.data = None
self._target = None
self._callback = None
def isAsynchronous(self) -> bool:
return False
def setAsynchronous(self, async_: bool):
pass
def toString(self) -> str:
return f"Message(what={self.what}, arg1={self.arg1}, arg2={self.arg2})"
# ═══════════════════════════════════════════════════════════════
# Looper
# ═══════════════════════════════════════════════════════════════
class Looper(Stub):
"""Looper — 消息循环"""
_main_looper: Optional["Looper"] = None
_thread_local = threading.local()
def __init__(self, quit_allowed: bool = True):
super().__init__()
self._thread = threading.current_thread()
self._running = False
self._message_queue: List[Message] = []
self._queue_lock = threading.Lock()
self._quit_allowed = quit_allowed
@staticmethod
def prepare():
"""为当前线程准备一个 Looper"""
looper = Looper()
Looper._thread_local.looper = looper
return looper
@staticmethod
def prepareMainLooper():
if Looper._main_looper is None:
Looper._main_looper = Looper.prepare()
@staticmethod
def getMainLooper() -> "Looper":
if Looper._main_looper is None:
Looper.prepareMainLooper()
return Looper._main_looper
@staticmethod
def myLooper() -> Optional["Looper"]:
return getattr(Looper._thread_local, "looper", None)
@staticmethod
def loop():
"""运行消息循环,处理到期的消息"""
looper = Looper.myLooper()
if looper is None:
raise RuntimeError("No Looper prepared")
looper._running = True
while looper._running:
msg = looper._next()
if msg is not None:
target = msg._target
if target is not None:
target.dispatchMessage(msg)
msg.recycle()
else:
# 无到期消息,短暂 sleep 避免忙等
_time.sleep(0.001)
def _next(self) -> Optional[Message]:
"""非阻塞地取出一条到期消息(when <= now)"""
with self._queue_lock:
now = SystemClock.uptimeMillis()
for i, msg in enumerate(self._message_queue):
if msg.when <= now:
return self._message_queue.pop(i)
return None
def _enqueue(self, msg: Message):
"""将消息按 when 时间顺序入队"""
with self._queue_lock:
inserted = False
for i, m in enumerate(self._message_queue):
if msg.when < m.when:
self._message_queue.insert(i, msg)
inserted = True
break
if not inserted:
self._message_queue.append(msg)
def _remove_callbacks(self, callback):
"""从队列中移除匹配 callback 的消息"""
with self._queue_lock:
self._message_queue = [
m for m in self._message_queue
if m._callback is not callback
]
def _remove_messages(self, what: int):
"""从队列中移除匹配 what 的消息"""
with self._queue_lock:
self._message_queue = [
m for m in self._message_queue
if m.what != what
]
def _has_messages(self, what: int) -> bool:
"""检查队列中是否有匹配 what 的消息"""
with self._queue_lock:
return any(m.what == what for m in self._message_queue)
def quit(self):
"""退出消息循环"""
if not self._quit_allowed:
raise RuntimeError("Main Looper is not allowed to quit")
with self._queue_lock:
self._running = False
self._message_queue.clear()
def quitSafely(self):
"""安全退出,仅停止循环(已入队消息不再处理)"""
with self._queue_lock:
self._running = False
def isCurrentThread(self) -> bool:
return threading.current_thread() == self._thread
def getThread(self) -> threading.Thread:
return self._thread
def getQueue(self):
return self._message_queue
def dump(self, pw: Any, prefix: str):
pass
def toString(self) -> str:
return f"Looper({self._thread.name})"
# ═══════════════════════════════════════════════════════════════
# Handler
# ═══════════════════════════════════════════════════════════════
class Handler(Stub):
"""Handler — 消息处理器"""
def __init__(self, looper: Optional[Looper] = None, callback: Optional[Callable] = None):
super().__init__()
self._looper = looper or Looper.getMainLooper()
self._callback = callback
self._async = False
def handleMessage(self, msg: Message):
pass
def dispatchMessage(self, msg: Message):
if msg._callback:
msg._callback()
elif self._callback:
self._callback(msg)
else:
self.handleMessage(msg)
def post(self, r: Callable) -> bool:
msg = Message.obtain(self)
msg._callback = r
return self.sendMessage(msg)
def postDelayed(self, r: Callable, delay_ms: int) -> bool:
msg = Message.obtain(self)
msg._callback = r
return self.sendMessageDelayed(msg, delay_ms)
def postAtTime(self, r: Callable, uptime_ms: int) -> bool:
msg = Message.obtain(self)
msg._callback = r
msg.when = uptime_ms
return self.sendMessageAtTime(msg, uptime_ms)
def sendMessage(self, msg: Message) -> bool:
msg._target = self
looper = self._looper
if looper is not None and looper._running:
looper._enqueue(msg)
return True
# 当前线程无运行中的 Looper,回退到同步执行(保持兼容性)
self.dispatchMessage(msg)
return True
def sendEmptyMessage(self, what: int) -> bool:
msg = Message.obtain(self, what)
return self.sendMessage(msg)
def sendMessageDelayed(self, msg: Message, delay_ms: int) -> bool:
msg._target = self
msg.when = SystemClock.uptimeMillis() + delay_ms
looper = self._looper
if looper is not None and looper._running:
looper._enqueue(msg)
return True
# 回退到同步执行
self.dispatchMessage(msg)
return True
def sendMessageAtTime(self, msg: Message, uptime_ms: int) -> bool:
msg._target = self
msg.when = uptime_ms
looper = self._looper
if looper is not None and looper._running:
looper._enqueue(msg)
return True
self.dispatchMessage(msg)
return True
def sendMessageAtFrontOfQueue(self, msg: Message) -> bool:
msg._target = self
msg.when = 0
looper = self._looper
if looper is not None and looper._running:
with looper._queue_lock:
looper._message_queue.insert(0, msg)
return True
self.dispatchMessage(msg)
return True
def removeCallbacks(self, r: Callable):
looper = self._looper
if looper is not None:
looper._remove_callbacks(r)
def removeMessages(self, what: int):
looper = self._looper
if looper is not None:
looper._remove_messages(what)
def obtainMessage(self, what: int = 0) -> Message:
return Message.obtain(self, what)
def hasMessages(self, what: int) -> bool:
looper = self._looper
if looper is not None:
return looper._has_messages(what)
return False
def getLooper(self) -> Looper:
return self._looper
def toString(self) -> str:
return f"Handler({self.__class__.__name__})"
# ═══════════════════════════════════════════════════════════════
# HandlerThread
# ═══════════════════════════════════════════════════════════════
class HandlerThread(threading.Thread, Stub):
"""HandlerThread — 带 Looper 的工作线程"""
def __init__(self, name: str, priority: int = Process.THREAD_PRIORITY_DEFAULT):
super().__init__()
Stub.__init__(self)
self._name = name
self._priority = priority
self._looper: Optional[Looper] = None
self._started = threading.Event()
def run(self):
Looper.prepare()
self._looper = Looper.myLooper()
self._started.set()
Looper.loop()
def getLooper(self) -> Optional[Looper]:
self._started.wait()
return self._looper
def getThreadId(self) -> int:
return self.ident or 0
def quit(self) -> bool:
if self._looper:
self._looper.quit()
return True
return False
def quitSafely(self) -> bool:
return self.quit()
# ═══════════════════════════════════════════════════════════════
# AsyncTask Executor (守护线程池)
# ═══════════════════════════════════════════════════════════════
class _AsyncTaskExecutor:
"""守护线程池执行器 — 用于 AsyncTask 后台执行,不阻塞程序退出。
使用 BoundedSemaphore 限制并发数,每个任务在独立的守护线程中运行。
"""
def __init__(self, max_workers: int = 4):
self._max_workers = max_workers
self._semaphore = threading.BoundedSemaphore(max_workers)
self._shutdown_flag = False
def submit(self, fn, *args, **kwargs):
if self._shutdown_flag:
raise RuntimeError("Executor has been shut down")
self._semaphore.acquire()
def _run():
try:
fn(*args, **kwargs)
finally:
self._semaphore.release()
t = threading.Thread(target=_run, daemon=True)
t.start()
def execute(self, command):
self.submit(command)
def shutdown(self, wait: bool = True):
self._shutdown_flag = True
# ═══════════════════════════════════════════════════════════════
# AsyncTask
# ═══════════════════════════════════════════════════════════════
class AsyncTask(Stub):
"""AsyncTask — 异步任务"""
Status = type("Status", (), {"PENDING": 0, "RUNNING": 1, "FINISHED": 2})
SERIAL_EXECUTOR = None
THREAD_POOL_EXECUTOR = None
def __init__(self):
super().__init__()
self._status = AsyncTask.Status.PENDING
self._result: Any = None
self._cancelled = False
self._handler = Handler(Looper.getMainLooper())
def doInBackground(self, *params) -> Any:
raise NotImplementedError
def onPreExecute(self):
pass
def onPostExecute(self, result: Any):
pass
def onProgressUpdate(self, *values):
pass
def onCancelled(self, result: Any = None):
pass
def execute(self, *params) -> "AsyncTask":
return self.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, *params)
def executeOnExecutor(self, exec: Any, *params) -> "AsyncTask":
self._status = AsyncTask.Status.RUNNING
self.onPreExecute()
exec.submit(self._run_background, params)
return self
def _run_background(self, params):
"""在后台线程中执行 doInBackground,完成后通过 Handler 回调主线程"""
try:
self._result = self.doInBackground(*params)
except Exception as e:
self._result = e
self._status = AsyncTask.Status.FINISHED
if self._cancelled:
self._handler.post(lambda: self.onCancelled(self._result))
else:
self._handler.post(lambda: self.onPostExecute(self._result))
def get(self) -> Any:
return self._result
def getStatus(self) -> int:
return self._status
def isCancelled(self) -> bool:
return self._cancelled
def cancel(self, may_interrupt_if_running: bool) -> bool:
self._cancelled = True
return True
def publishProgress(self, *values):
self._handler.post(lambda: self.onProgressUpdate(*values))
# 初始化默认执行器
AsyncTask.THREAD_POOL_EXECUTOR = _AsyncTaskExecutor(max_workers=4)
AsyncTask.SERIAL_EXECUTOR = _AsyncTaskExecutor(max_workers=1)
# ═══════════════════════════════════════════════════════════════
# CountDownTimer
# ═══════════════════════════════════════════════════════════════
class CountDownTimer(Stub):
"""CountDownTimer — 倒计时"""
def __init__(self, millis_in_future: int, count_down_interval: int):
super().__init__()
self._millis_in_future = millis_in_future
self._interval = count_down_interval
self._cancelled = False
def onTick(self, millis_until_finished: int):
pass
def onFinish(self):
pass
def start(self) -> "CountDownTimer":
self._cancelled = False
remaining = self._millis_in_future
while remaining > 0 and not self._cancelled:
self.onTick(remaining)
_time.sleep(self._interval / 1000.0)
remaining -= self._interval
if not self._cancelled:
self.onFinish()
return self
def cancel(self):
self._cancelled = True
# ═══════════════════════════════════════════════════════════════
# Messenger
# ═══════════════════════════════════════════════════════════════
class Messenger(Stub):
"""Messenger — 跨进程消息传递"""
def __init__(self, handler: Handler):
super().__init__()
self._handler = handler
def send(self, message: Message):
self._handler.sendMessage(message)
def getBinder(self):
return None
@staticmethod
def obtain(handler: Handler) -> "Messenger":
return Messenger(handler)
# ═══════════════════════════════════════════════════════════════
# PowerManager / PowerManagerWakeLock
# ═══════════════════════════════════════════════════════════════
class PowerManager(Stub):
"""PowerManager — 电源管理"""
ACQUIRE_CAUSES_WAKEUP = 0x10000000
DOZE_WAKE_LOCK = 0x00000040
DRAW_WAKE_LOCK = 0x00000080
FULL_WAKE_LOCK = 0x0000001A
LOCATION_HARDWARE_POWER_MODE = 0x00000080
ON_AFTER_RELEASE = 0x20000000
PARTIAL_WAKE_LOCK = 0x00000001
PROXIMITY_SCREEN_OFF_WAKE_LOCK = 0x00000020
SCREEN_BRIGHT_WAKE_LOCK = 0x0000000A
SCREEN_DIM_WAKE_LOCK = 0x00000006
WAKE_LOCK_LEVEL_MASK = 0x0000FFFF
def __init__(self):
super().__init__()
self._is_interactive = True
self._is_power_save = False
self._is_device_idle = False
def newWakeLock(self, level_and_flags: int, tag: str) -> "PowerManagerWakeLock":
return PowerManagerWakeLock(level_and_flags, tag)
def isInteractive(self) -> bool:
if _USE_LINUX:
return self.isScreenOn()
return self._is_interactive
def isScreenOn(self) -> bool:
"""屏幕是否点亮 — 在 Linux 上检查 DISPLAY 环境变量"""
if _USE_LINUX:
import os as _os_mod
display = _os_mod.environ.get("DISPLAY", "")
if display:
return True
# WAYLAND_DISPLAY 作为回退
wayland = _os_mod.environ.get("WAYLAND_DISPLAY", "")
return bool(wayland)
return self._is_interactive
def isPowerSaveMode(self) -> bool:
return self._is_power_save
def isDeviceIdleMode(self) -> bool:
return self._is_device_idle
def isIgnoringBatteryOptimizations(self, package_name: str) -> bool:
return True
def isSustainedPerformanceModeSupported(self) -> bool:
return False
def reboot(self, reason: Optional[str] = None):
pass
def goToSleep(self, time_ms: int):
pass
def wakeUp(self, time_ms: int):
pass
def userActivity(self, when: int, no_change_lights: bool = False):
pass
class PowerManagerWakeLock(Stub):
"""PowerManagerWakeLock — 唤醒锁"""
def __init__(self, level_and_flags: int, tag: str):
super().__init__()
self._level_and_flags = level_and_flags
self._tag = tag
self._held = False
self._work_source = None
self._history_tag = None
def acquire(self, timeout_ms: int = 0):
self._held = True
sys.stderr.write(f"[PowerManager] acquire wakelock: {self._tag}\n")
def acquireLocked(self):
self._held = True
def release(self, flags: int = 0):
self._held = False
sys.stderr.write(f"[PowerManager] release wakelock: {self._tag}\n")
def isHeld(self) -> bool:
return self._held
def setWorkSource(self, work_source: Any):
self._work_source = work_source
def setReferenceCounted(self, value: bool):
pass
def setHistoryTag(self, tag: str):
self._history_tag = tag
def toString(self) -> str:
return f"WakeLock({self._tag}, held={self._held})"
# ═══════════════════════════════════════════════════════════════
# Vibrator / VibratorEffect
# ═══════════════════════════════════════════════════════════════
class Vibrator(Stub):
"""Vibrator — 振动器"""
def __init__(self):
super().__init__()
def vibrate(self, milliseconds: int):
sys.stderr.write(f"[Vibrator] vibrate: {milliseconds}ms\n")
def vibrate(self, pattern: List[int], repeat: int):
sys.stderr.write(f"[Vibrator] vibrate pattern: {pattern}, repeat={repeat}\n")
def cancel(self):
sys.stderr.write("[Vibrator] cancel\n")
def hasVibrator(self) -> bool:
return True
def hasAmplitudeControl(self) -> bool:
return False
def areEffectsSupported(self, effect_ids: List[int]) -> List[int]:
return [0] * len(effect_ids)
def areAllEffectsSupported(self, effect_ids: List[int]) -> List[int]:
return [0] * len(effect_ids)
class VibratorEffect(Stub):
"""VibratorEffect — 振动效果"""
def __init__(self, effect_id: int = 0):
super().__init__()
self._effect_id = effect_id
@staticmethod
def createOneShot(milliseconds: int, amplitude: int) -> "VibratorEffect":
return VibratorEffect(0)
@staticmethod
def createWaveform(pattern: List[int], repeat: int) -> "VibratorEffect":
return VibratorEffect(0)
@staticmethod
def createPredefined(effect_id: int) -> "VibratorEffect":
return VibratorEffect(effect_id)
# ═══════════════════════════════════════════════════════════════
# BatteryManager
# ═══════════════════════════════════════════════════════════════
class BatteryManager(Stub):
"""BatteryManager — 电池管理"""
BATTERY_PROPERTY_CHARGE_COUNTER = 1
BATTERY_PROPERTY_CURRENT_NOW = 2
BATTERY_PROPERTY_CURRENT_AVERAGE = 3
BATTERY_PROPERTY_CAPACITY = 4
BATTERY_PROPERTY_STATUS = 5
BATTERY_PROPERTY_ENERGY_COUNTER = 6
BATTERY_PROPERTY_BATTERY_NOW = 7
BATTERY_PROPERTY_BATTERY_LOW = 8
BATTERY_STATUS_UNKNOWN = 1
BATTERY_STATUS_CHARGING = 2
BATTERY_STATUS_DISCHARGING = 3
BATTERY_STATUS_NOT_CHARGING = 4
BATTERY_STATUS_FULL = 5
BATTERY_HEALTH_UNKNOWN = 1
BATTERY_HEALTH_GOOD = 2
BATTERY_HEALTH_OVERHEAT = 3
BATTERY_HEALTH_DEAD = 4
BATTERY_HEALTH_OVER_VOLTAGE = 5
BATTERY_HEALTH_UNSPECIFIED_FAILURE = 6
BATTERY_HEALTH_COLD = 7
EXTRA_STATUS = "status"
EXTRA_HEALTH = "health"
EXTRA_PRESENT = "present"
EXTRA_LEVEL = "level"
EXTRA_SCALE = "scale"
EXTRA_ICON_SMALL = "icon-small"
EXTRA_PLUGGED = "plugged"
EXTRA_VOLTAGE = "voltage"
EXTRA_TEMPERATURE = "temperature"
EXTRA_TECHNOLOGY = "technology"
EXTRA_BATTERY_LOW = "battery_low"
EXTRA_CHARGE_COUNTER = "charge_counter"
BATTERY_PLUGGED_AC = 1
BATTERY_PLUGGED_USB = 2
BATTERY_PLUGGED_WIRELESS = 4
def __init__(self):
super().__init__()
self._capacity = 85
self._status = self.BATTERY_STATUS_CHARGING
self._health = self.BATTERY_HEALTH_GOOD
self._present = True
self._level = 85
self._plugged = self.BATTERY_PLUGGED_AC
self._voltage = 4200
self._temperature = 250
self._technology = "Li-ion"
self._charge_counter = 3500000
self._current_now = -500000
self._current_avg = -450000
self._energy_counter = 15000000
if _USE_LINUX:
self._refresh_from_linux()
_LINUX_STATUS_MAP = {
"charging": 2, # BATTERY_STATUS_CHARGING
"discharging": 3, # BATTERY_STATUS_DISCHARGING
"not charging": 4, # BATTERY_STATUS_NOT_CHARGING
"full": 5, # BATTERY_STATUS_FULL
"unknown": 1, # BATTERY_STATUS_UNKNOWN
}
def _get_linux_battery_info(self) -> dict:
"""从 LinuxPower 获取真实电池信息"""
try:
return LinuxPower.get_battery_info() or {}
except Exception:
return {}
def _refresh_from_linux(self):
"""用 Linux 真实电池信息刷新内部状态"""
info = self._get_linux_battery_info()
if not info:
return
self._present = bool(info.get("present", False))
level = info.get("level", -1)
if self._present and isinstance(level, (int, float)) and level >= 0:
self._level = int(level)
self._capacity = int(level)
else:
# 无电池或电量未知
self._level = -1
self._capacity = -1
status_str = str(info.get("status", "unknown")).lower()
self._status = self._LINUX_STATUS_MAP.get(status_str, self.BATTERY_STATUS_UNKNOWN)
voltage = info.get("voltage", 0)
if isinstance(voltage, (int, float)):
# LinuxPower 返回伏特, Android 期望毫伏
self._voltage = int(voltage * 1000)
temperature = info.get("temperature", 0)
if isinstance(temperature, (int, float)):
# LinuxPower 返回摄氏度, Android 期望十分之一度
self._temperature = int(temperature * 10)
self._technology = info.get("technology", "") or "Li-ion"
# 充电状态决定 plugged
if self._status == self.BATTERY_STATUS_CHARGING:
self._plugged = self.BATTERY_PLUGGED_AC
else:
self._plugged = 0
def getIntProperty(self, prop_id: int) -> int:
if _USE_LINUX:
self._refresh_from_linux()
if prop_id == self.BATTERY_PROPERTY_CAPACITY:
return self._capacity
if prop_id == self.BATTERY_PROPERTY_STATUS:
return self._status
if prop_id == self.BATTERY_PROPERTY_CHARGE_COUNTER:
return self._charge_counter
if prop_id == self.BATTERY_PROPERTY_CURRENT_NOW:
return self._current_now
if prop_id == self.BATTERY_PROPERTY_CURRENT_AVERAGE:
return self._current_avg
if prop_id == self.BATTERY_PROPERTY_ENERGY_COUNTER:
return self._energy_counter
return -1
def getLongProperty(self, prop_id: int) -> int:
return self.getIntProperty(prop_id)
def isCharging(self) -> bool:
if _USE_LINUX:
self._refresh_from_linux()
return self._status == self.BATTERY_STATUS_CHARGING
def isPresent(self) -> bool:
"""电池是否存在"""
if _USE_LINUX:
self._refresh_from_linux()
return self._present
def getLevel(self) -> int:
"""电池电量 (0-100, -1 表示未知)"""
if _USE_LINUX:
self._refresh_from_linux()
return self._level
def getVoltage(self) -> int:
"""电池电压 (毫伏)"""
if _USE_LINUX:
self._refresh_from_linux()
return self._voltage
def getTemperature(self) -> int:
"""电池温度 (十分之一摄氏度)"""
if _USE_LINUX:
self._refresh_from_linux()
return self._temperature
def getTechnology(self) -> str:
"""电池技术"""
if _USE_LINUX:
self._refresh_from_linux()
return self._technology
def getPlugType(self) -> int:
"""充电类型"""
if _USE_LINUX:
self._refresh_from_linux()
return self._plugged
def getStatus(self) -> int:
"""电池状态"""
if _USE_LINUX:
self._refresh_from_linux()
return self._status
def computeChargeTimeRemaining(self) -> int:
if _USE_LINUX:
# 无电池或已充满时返回 -1
if not self._present or self._status == self.BATTERY_STATUS_FULL:
return -1
return 1800000 # 30 minutes
def toString(self) -> str:
return f"BatteryManager(level={self._level}%, charging={self.isCharging()})"
# ═══════════════════════════════════════════════════════════════
# 异常类
# ═══════════════════════════════════════════════════════════════
class NetworkOnMainThreadException(RuntimeError):
"""网络操作在主线程上执行"""
pass
class TransactionTooLargeException(RuntimeError):
"""事务数据太大"""
pass
class OperationCanceledException(RuntimeError):
"""操作被取消"""
pass
# ═══════════════════════════════════════════════════════════════
# 其他工具类
# ═══════════════════════════════════════════════════════════════
class ConditionVariable(Stub):
"""ConditionVariable — 条件变量"""
def __init__(self):
super().__init__()
self._cond = threading.Condition()
self._open = False
def block(self, timeout_ms: int = 0):
with self._cond:
if timeout_ms <= 0:
while not self._open:
self._cond.wait()
else:
if not self._open:
self._cond.wait(timeout_ms / 1000.0)
def open(self):
with self._cond:
self._open = True
self._cond.notify_all()
def close(self):
with self._cond:
self._open = False
class Semaphore(Stub):
"""Semaphore — 信号量"""
def __init__(self, permits: int):
super().__init__()
self._sem = threading.Semaphore(permits)
def acquire(self):
self._sem.acquire()
def tryAcquire(self) -> bool:
return self._sem.acquire(blocking=False)
def release(self):
self._sem.release()
def availablePermits(self) -> int:
return self._sem._value
class TokenWatcher(Stub):
"""TokenWatcher — 令牌监视器"""
def __init__(self, handler: Handler, tag: str):
super().__init__()
def acquire(self, token: Any, tag: str):
pass
def release(self, token: Any):
pass
def isAcquired(self) -> bool:
return False
def dump(self):
pass
class WorkSource(Stub):
"""WorkSource — 工作来源"""
def __init__(self, uid: int = 0):
super().__init__()
self._uids: List[int] = [uid] if uid else []
def add(self, uid: int):
if uid not in self._uids:
self._uids.append(uid)
def remove(self, uid: int):
if uid in self._uids:
self._uids.remove(uid)
def get(self, index: int) -> int:
if 0 <= index < len(self._uids):
return self._uids[index]
return 0
def size(self) -> int:
return len(self._uids)
def clear(self):
self._uids.clear()
def set(self, ws: "WorkSource"):
if ws:
self._uids = list(ws._uids)
def toString(self) -> str:
return f"WorkSource({self._uids})"
class UserHandle(Stub):
"""UserHandle — 用户句柄"""
USER_ALL = -1
USER_CURRENT = -2
USER_CURRENT_OR_SELF = -3
USER_NULL = -10000
USER_OWNER = 0
USER_SYSTEM = 0
def __init__(self, user_id: int = 0):
super().__init__()
self._user_id = user_id
@staticmethod
def myUserId() -> int:
return 0
@staticmethod
def getUserHandleForUid(uid: int) -> "UserHandle":
return UserHandle(uid // 100000)
@staticmethod
def getUserId(uid: int) -> int:
return uid // 100000
@staticmethod
def getUid(user_id: int, app_id: int) -> int:
return user_id * 100000 + app_id
@staticmethod
def getAppId(uid: int) -> int:
return uid % 100000
def getIdentifier(self) -> int:
return self._user_id
def hashCode(self) -> int:
return self._user_id
def toString(self) -> str:
return f"UserHandle({self._user_id})"
class DropBoxManager(Stub):
"""DropBoxManager — 系统日志收集"""
IS_EMPTY = 0
IS_TEXT = 1
IS_GZIPPED = 2
class Entry(Stub):
def __init__(self, tag: str, milliseconds: int):
super().__init__()
self._tag = tag
self._millis = milliseconds
self._text = ""
def getTag(self) -> str:
return self._tag
def getTimeMillis(self) -> int:
return self._millis
def getText(self, max_bytes: int) -> Optional[str]:
return self._text
def getFlags(self, max_bytes: int) -> int:
return DropBoxManager.IS_TEXT
def close(self):
pass
def __init__(self):
super().__init__()
self._entries: List[DropBoxManager.Entry] = []
def addText(self, tag: str, text: str):
entry = DropBoxManager.Entry(tag, int(_time.time() * 1000))
entry._text = text
self._entries.append(entry)
def getNextEntry(self, tag: str, milliseconds: int) -> Optional[Entry]:
for entry in self._entries:
if entry.getTimeMillis() > milliseconds:
if not tag or entry.getTag() == tag:
return entry
return None
def dump(self, pw: Any, prefix: str):
pass
class FileObserver(Stub):
"""FileObserver — 文件监听"""
ACCESS = 0x00000001
MODIFY = 0x00000002
ATTRIB = 0x00000004
CLOSE_WRITE = 0x00000008
CLOSE_NOWRITE = 0x00000010
OPEN = 0x00000020
MOVED_FROM = 0x00000040
MOVED_TO = 0x00000080
CREATE = 0x00000100
DELETE = 0x00000200
DELETE_SELF = 0x00000400
MOVE_SELF = 0x00000800
ALL_EVENTS = 0x00000FFF
def __init__(self, path: str):
super().__init__()
self._path = path
self._watching = False
def startWatching(self):
self._watching = True
def stopWatching(self):
self._watching = False
def onEvent(self, event: int, path: Optional[str]):
pass
def finalize(self):
pass
class FileUtils(Stub):
"""FileUtils — 文件工具"""
@staticmethod
def readFileToString(path):
try:
with open(path, "r", encoding="utf-8") as f:
return f.read()
except Exception:
return ""
@staticmethod
def stringToFile(path, content):
try:
with open(path, "w", encoding="utf-8") as f:
f.write(content)
return True
except Exception:
return False
@staticmethod
def copyFile(src, dst):
try:
import shutil
shutil.copy2(src, dst)
return True
except Exception:
return False
@staticmethod
def deleteDirectory(path):
try:
import shutil
shutil.rmtree(path)
return True
except Exception:
return False
@staticmethod
def deleteContents(path):
try:
import shutil
for entry in _os.listdir(path):
full = _os.path.join(path, entry)
if _os.path.isdir(full):
shutil.rmtree(full)
else:
_os.remove(full)
return True
except Exception:
return False
@staticmethod
def deleteOlderFiles(dir_: Any, min_count: int, min_age_ms: int):
pass
class PatternMatcher(Stub):
"""PatternMatcher — 模式匹配器"""
PATTERN_LITERAL = 0
PATTERN_PREFIX = 1
PATTERN_SIMPLE_GLOB = 2
PATTERN_ADVANCED_GLOB = 3
PATTERN_SUFFIX = 4
def __init__(self, pattern: str, type_: int):
super().__init__()
self._pattern = pattern
self._type = type_
def getPath(self) -> str:
return self._pattern
def getType(self) -> int:
return self._type
def match(self, str_: str) -> bool:
if self._type == self.PATTERN_LITERAL:
return str_ == self._pattern
if self._type == self.PATTERN_PREFIX:
return str_.startswith(self._pattern)
if self._type == self.PATTERN_SUFFIX:
return str_.endswith(self._pattern)
if self._type == self.PATTERN_SIMPLE_GLOB:
import fnmatch
return fnmatch.fnmatch(str_, self._pattern)
return str_ == self._pattern
def toString(self) -> str:
return f"PatternMatcher({self._pattern}, type={self._type})"
# ═══════════════════════════════════════════════════════════════
# __all__
# ═══════════════════════════════════════════════════════════════
__all__ = [
"Bundle",
"BaseBundle",
"PersistableBundle",
"Handler",
"Looper",
"Message",
"HandlerThread",
"PowerManager",
"PowerManagerWakeLock",
"Vibrator",
"VibratorEffect",
"Build",
"SystemClock",
"Environment",
"Parcel",
"Parcelable",
"Process",
"AsyncTask",
"CountDownTimer",
"Messenger",
"BatteryManager",
"PatternMatcher",
"ConditionVariable",
"Semaphore",
"TokenWatcher",
"WorkSource",
"UserHandle",
"DropBoxManager",
"FileObserver",
"FileUtils",
"NetworkOnMainThreadException",
"TransactionTooLargeException",
"OperationCanceledException",
]