Files
Android-pyApi/android_pyapi/android/os.py
T
shuiyu1123 bfe27fdc08 feat: Android-pyApi v1.0 - 全面翻译 Android SDK API 为 Python
52 个模块覆盖 Android + Java + org.json 标准库
2026-06-24 11:16:16 +00:00

1660 lines
48 KiB
Python

"""
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,
)
# ═══════════════════════════════════════════════════════════════
# 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
# ═══════════════════════════════════════════════════════════════
# 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: int):
pass
@staticmethod
def sendSignal(pid: int, signal: int):
pass
@staticmethod
def setThreadPriority(priority: int):
pass
@staticmethod
def setThreadPriority(tid: int, priority: int):
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 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
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):
super().__init__()
self._thread = threading.current_thread()
self._running = False
self._message_queue: List[Message] = []
self._quit_allowed = True
@staticmethod
def prepare():
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
def quit(self):
self._running = False
def quitSafely(self):
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
msg.when = int(_time.time() * 1000) + delay_ms
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
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 = int(_time.time() * 1000) + delay_ms
self.dispatchMessage(msg)
return True
def sendMessageAtTime(self, msg: Message, uptime_ms: int) -> bool:
msg._target = self
msg.when = uptime_ms
self.dispatchMessage(msg)
return True
def sendMessageAtFrontOfQueue(self, msg: Message) -> bool:
msg._target = self
self.dispatchMessage(msg)
return True
def removeCallbacks(self, r: Callable):
pass
def removeMessages(self, what: int):
pass
def obtainMessage(self, what: int = 0) -> Message:
return Message.obtain(self, what)
def hasMessages(self, what: int) -> bool:
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
# ═══════════════════════════════════════════════════════════════
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
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":
self._status = AsyncTask.Status.RUNNING
self.onPreExecute()
try:
self._result = self.doInBackground(*params)
except Exception as e:
self._result = e
self._status = AsyncTask.Status.FINISHED
if not self._cancelled:
self.onPostExecute(self._result)
return self
def executeOnExecutor(self, exec: Any, *params) -> "AsyncTask":
return self.execute(*params)
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.onProgressUpdate(*values)
# ═══════════════════════════════════════════════════════════════
# 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:
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
def getIntProperty(self, prop_id: int) -> int:
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:
return self._status == self.BATTERY_STATUS_CHARGING
def computeChargeTimeRemaining(self) -> int:
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(file: Any) -> str:
return ""
@staticmethod
def stringToFile(file: Any, string: str):
pass
@staticmethod
def copyFile(src: Any, dest: Any) -> bool:
return True
@staticmethod
def deleteDirectory(dir_: Any) -> bool:
return True
@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",
]