""" 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", ]