feat: 深度完善 — 存根转真实实现、UI类方法补全、Java集合/IO增强

存根转真实实现:
- ContentResolver: query/insert/update/delete对file://URI真实文件操作, getType用mimetypes
- Context: getResources/getAssets/getString/getColor 委托真实Resources
- Bitmap.sameAs: PIL像素比对
- Canvas: quickReject/drawTextOnPath/drawPicture/drawDoubleRoundRect 真实实现
- Paint: measureText/breakText/getTextWidths/getFontMetrics/getTextBounds 用PIL字体
- PathMeasure: 真实路径展平/长度计算/坐标切线提取
- Path.op/Region.op: 布尔运算
- Camera: 3D变换矩阵计算
- SystemClock.setCurrentTimeMillis: date -s命令
- Environment.isExternalStorageRemovable: /proc/mounts检查
- Process.myUid: os.getuid()
- PowerManager.isPowerSaveMode: CPU governor检查
- Vibrator: Linux LED振动器设备支持
- FileObserver: 轮询线程检测文件变化
- SensorManager.getRotationMatrix: 完整旋转矩阵算法
- BatteryManager: LinuxPower真实电池数据
- Geocoder: Nominatim API逆地理编码
- LocationManager: addProximityAlert/setTestProviderLocation

UI类方法补全:
- TextView: setPaddingRelative/getTextColor/setBreakStrategy/setJustificationMode
- ImageView: setColorFilter/getColorFilter/clearColorFilter
- CheckBox/Switch: setOnCheckedChangeListener
- ListView: clearChoices
- ViewGroup: setLayoutTransition/setTouchscreenBlocksFocus/getChildVisibleRect
- MotionEvent: getHistoricalX/Y/Pressure/EventTime/addBatch/getEdgeFlags/setAction

Java集合增强:
- ArrayList: spliterator/stream
- HashSet: spliterator/stream/removeIf
- TreeMap: replaceAll/compute/computeIfAbsent/computeIfPresent/merge
- LinkedHashMap: clone (保留access_order)
- PriorityQueue: spliterator/clone

Java IO增强:
- BufferedWriter: append/check
- PrintWriter: append
- ByteArrayOutputStream: writeTo
- ByteArrayInputStream: markSupported
- BufferedInputStream: available/mark/reset/markSupported + 修复_fill缓冲区填充bug
- SequenceInputStream: 补全实现(Enumeration/多流/跨流聚合读取)

修复:
- ViewGroup.addView: 合并重复定义为智能参数分派
- view_ext.ViewGroup: 继承view.ViewGroup
- view_ext.KeyEvent: 继承view.KeyEvent
- hardware_sensor_ext.SensorManager: 继承hardware.SensorManager
- app_fragment: 使用java.lang.IllegalStateException
- content_intent.Intent: setData/getScheme正确从Uri提取scheme
- __init__.py: 补全Fragment/KeyEvent/MotionEvent/TrafficStats/RecyclerView/TreeMap/Vibrator等导出

统计: 221模块, 3662类, 30952方法, 182302行
This commit is contained in:
shuiyu1123 committed 2026-06-25 00:17:50 +00:00
1 parent 39b1da37c9
commit 4235f8692c
13 files changed
+2248 -163

No files matched your search

+332 -27
View File
@@ -115,11 +115,46 @@ class Build(Stub):
@staticmethod
def getRadioVersion() -> str:
return ""
"""返回基带/无线电版本。桌面端无无线电硬件,返回空字符串。"""
return Build.RADIO
@staticmethod
def getSerial() -> str:
return "unknown"
"""返回设备序列号。尝试从 /sys 或 /proc 读取真实硬件序列号。"""
# 尝试从 /sys/class/android_usb 读取
try:
for name in _os.listdir("/sys/class/android_usb"):
serial_path = f"/sys/class/android_usb/{name}/iSerial"
if _os.path.exists(serial_path):
with open(serial_path, "r") as f:
serial = f.read().strip()
if serial:
return serial
except (OSError, IOError):
pass
# 尝试从 /proc/cpuinfo 读取 Serial 字段
try:
with open("/proc/cpuinfo", "r") as f:
for line in f:
if line.lower().startswith("serial"):
parts = line.split(":", 1)
if len(parts) == 2:
serial = parts[1].strip()
if serial and serial != "0" * len(serial):
return serial
except (OSError, IOError):
pass
# 尝试从 /sys/class/dmi/id/product_serial 读取
try:
path = "/sys/class/dmi/id/product_serial"
if _os.path.exists(path):
with open(path, "r") as f:
serial = f.read().strip()
if serial:
return serial
except (OSError, IOError):
pass
return Build.SERIAL
@staticmethod
def getFingerprint() -> str:
@@ -201,7 +236,17 @@ class SystemClock(Stub):
@staticmethod
def setCurrentTimeMillis(millis: int) -> bool:
return False
"""尝试设置系统时间。需要 root 权限,通常在桌面端会失败。"""
try:
import subprocess
seconds = millis / 1000.0
# 尝试使用 date 命令设置时间
result = subprocess.run(
["date", "-s", f"@{int(seconds)}"],
capture_output=True, timeout=5)
return result.returncode == 0
except Exception:
return False
# ═══════════════════════════════════════════════════════════════
@@ -268,6 +313,20 @@ class Environment(Stub):
@staticmethod
def isExternalStorageRemovable(path: Optional[str] = None) -> bool:
"""判断外部存储是否可移除。通过检查 /proc/mounts 判断。"""
try:
check_path = path or _sdcard_root
with open("/proc/mounts", "r") as f:
for line in f:
parts = line.split()
if len(parts) >= 3 and check_path in parts[1]:
# 检查挂载选项中是否包含 SD 卡相关设备
device = parts[0]
if "/sd" in device or "/mmc" in device or "/usb" in device:
return True
return False
except (OSError, IOError):
pass
return False
@staticmethod
@@ -309,7 +368,8 @@ class Process(Stub):
@staticmethod
def myUid() -> int:
return 10001
"""返回当前进程的真实 UID。"""
return _os.getuid()
@staticmethod
def myPid() -> int:
@@ -331,11 +391,15 @@ class Process(Stub):
pass
@staticmethod
def setThreadPriority(priority: int):
pass
@staticmethod
def setThreadPriority(tid, priority):
def setThreadPriority(*args):
"""设置线程优先级。支持 setThreadPriority(priority) 和 setThreadPriority(tid, priority)。"""
if len(args) == 1:
tid = 0
priority = args[0]
elif len(args) == 2:
tid, priority = args
else:
return
try:
_os.setpriority(_os.PRIO_PROCESS, tid, priority)
except (OSError, PermissionError):
@@ -1006,7 +1070,20 @@ class Looper(Stub):
return self._message_queue
def dump(self, pw: Any, prefix: str):
pass
"""将 DropBox 条目转储到给定的 writer。"""
try:
if hasattr(pw, "write"):
pw.write(f"{prefix}DropBoxManager entries:\n")
for entry in self._entries:
pw.write(f"{prefix} [{entry.getTag()}] @ {entry.getTimeMillis()}: "
f"{entry.getText(1024)}\n")
elif hasattr(pw, "println"):
pw.println(f"{prefix}DropBoxManager entries:")
for entry in self._entries:
pw.println(f"{prefix} [{entry.getTag()}] @ {entry.getTimeMillis()}: "
f"{entry.getText(1024)}")
except Exception:
pass
def toString(self) -> str:
return f"Looper({self._thread.name})"
@@ -1377,6 +1454,17 @@ class PowerManager(Stub):
return self._is_interactive
def isPowerSaveMode(self) -> bool:
"""检查是否处于省电模式。读取 /sys 中的电源相关状态。"""
try:
# 检查 CPU 调速器是否为 powersave
gov_path = "/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor"
if _os.path.exists(gov_path):
with open(gov_path, "r") as f:
governor = f.read().strip()
if governor == "powersave":
return True
except (OSError, IOError):
pass
return self._is_power_save
def isDeviceIdleMode(self) -> bool:
@@ -1389,16 +1477,29 @@ class PowerManager(Stub):
return False
def reboot(self, reason: Optional[str] = None):
pass
"""重启设备。桌面端尝试执行 reboot 命令(通常需要 root)。"""
try:
import subprocess
cmd = ["reboot"]
if reason:
cmd.append(reason)
subprocess.run(cmd, capture_output=True, timeout=5)
except Exception:
sys.stderr.write(f"[PowerManager] reboot: {reason or ''}\n")
def goToSleep(self, time_ms: int):
pass
"""使设备进入睡眠。桌面端无实际效果。"""
self._is_interactive = False
sys.stderr.write(f"[PowerManager] goToSleep at {time_ms}\n")
def wakeUp(self, time_ms: int):
pass
"""唤醒设备。桌面端无实际效果。"""
self._is_interactive = True
sys.stderr.write(f"[PowerManager] wakeUp at {time_ms}\n")
def userActivity(self, when: int, no_change_lights: bool = False):
pass
"""报告用户活动事件。桌面端无实际效果。"""
self._is_interactive = True
class PowerManagerWakeLock(Stub):
@@ -1448,20 +1549,101 @@ class Vibrator(Stub):
def __init__(self):
super().__init__()
self._ff_device: Optional[str] = None
self._vibrating = False
def vibrate(self, milliseconds: int):
sys.stderr.write(f"[Vibrator] vibrate: {milliseconds}ms\n")
@staticmethod
def _find_ff_device() -> Optional[str]:
"""查找 Linux 力反馈设备。"""
try:
for name in _os.listdir("/dev/input"):
if name.startswith("event"):
path = f"/dev/input/{name}"
if _os.access(path, _os.W_OK):
return path
except (OSError, IOError):
pass
# 检查 /sys/class/leds/vibrator
try:
if _os.path.exists("/sys/class/leds/vibrator"):
return "/sys/class/leds/vibrator"
except (OSError, IOError):
pass
return None
def vibrate(self, pattern: List[int], repeat: int):
sys.stderr.write(f"[Vibrator] vibrate pattern: {pattern}, repeat={repeat}\n")
def vibrate(self, *args):
"""振动。支持 vibrate(milliseconds) 和 vibrate(pattern, repeat)。"""
if len(args) == 1 and isinstance(args[0], (int, float)):
milliseconds = int(args[0])
self._vibrating = True
if self._ff_device is None:
self._ff_device = self._find_ff_device()
if self._ff_device and self._ff_device.startswith("/sys/class/leds"):
try:
with open(_os.path.join(self._ff_device, "brightness"), "w") as f:
f.write("1")
import threading
def _stop():
_time.sleep(milliseconds / 1000.0)
try:
with open(_os.path.join(self._ff_device, "brightness"), "w") as f:
f.write("0")
except (OSError, IOError):
pass
self._vibrating = False
threading.Thread(target=_stop, daemon=True).start()
return
except (OSError, IOError):
pass
sys.stderr.write(f"[Vibrator] vibrate: {milliseconds}ms\n")
elif len(args) == 2 and isinstance(args[0], list):
pattern = args[0]
repeat = args[1]
if not pattern:
return
self._vibrating = True
import threading
def _run_pattern():
idx = 0
while True:
duration = pattern[idx % len(pattern)]
if idx % 2 == 0:
_time.sleep(duration / 1000.0)
else:
self.vibrate(duration)
_time.sleep(duration / 1000.0)
idx += 1
if repeat < 0 or idx >= len(pattern):
if repeat < 0:
continue
break
self._vibrating = False
threading.Thread(target=_run_pattern, daemon=True).start()
sys.stderr.write(f"[Vibrator] vibrate pattern: {pattern}, repeat={repeat}\n")
def cancel(self):
"""取消振动。"""
self._vibrating = False
if self._ff_device and self._ff_device.startswith("/sys/class/leds"):
try:
with open(_os.path.join(self._ff_device, "brightness"), "w") as f:
f.write("0")
except (OSError, IOError):
pass
sys.stderr.write("[Vibrator] cancel\n")
def hasVibrator(self) -> bool:
return True
"""检查是否有振动器硬件。"""
return self._find_ff_device() is not None
def hasAmplitudeControl(self) -> bool:
"""检查是否支持振幅控制。"""
try:
if _os.path.exists("/sys/class/leds/vibrator/max_brightness"):
with open("/sys/class/leds/vibrator/max_brightness", "r") as f:
return int(f.read().strip()) > 1
except (OSError, IOError, ValueError):
pass
return False
def areEffectsSupported(self, effect_ids: List[int]) -> List[int]:
@@ -1474,20 +1656,41 @@ class Vibrator(Stub):
class VibratorEffect(Stub):
"""VibratorEffect — 振动效果"""
EFFECT_CLICK = 0
EFFECT_DOUBLE_CLICK = 1
EFFECT_TICK = 2
EFFECT_THUD = 3
EFFECT_POP = 4
EFFECT_HEAVY_CLICK = 5
def __init__(self, effect_id: int = 0):
super().__init__()
self._effect_id = effect_id
self._timings: Optional[List[int]] = None
self._amplitudes: Optional[List[int]] = None
self._repeat = -1
@staticmethod
def createOneShot(milliseconds: int, amplitude: int) -> "VibratorEffect":
return VibratorEffect(0)
"""创建单次振动效果。"""
effect = VibratorEffect(0)
effect._timings = [0, milliseconds]
effect._amplitudes = [0, amplitude]
effect._repeat = -1
return effect
@staticmethod
def createWaveform(pattern: List[int], repeat: int) -> "VibratorEffect":
return VibratorEffect(0)
"""创建波形振动效果。"""
effect = VibratorEffect(0)
effect._timings = list(pattern)
effect._amplitudes = [255 if i % 2 == 1 else 0 for i in range(len(pattern))]
effect._repeat = repeat
return effect
@staticmethod
def createPredefined(effect_id: int) -> "VibratorEffect":
"""创建预定义振动效果。"""
return VibratorEffect(effect_id)
@@ -1755,18 +1958,38 @@ class TokenWatcher(Stub):
def __init__(self, handler: Handler, tag: str):
super().__init__()
self._handler = handler
self._tag = tag
self._tokens: Dict[int, str] = {}
def acquire(self, token: Any, tag: str):
pass
"""获取令牌。"""
self._tokens[id(token)] = tag
if len(self._tokens) == 1:
self.acquired()
def release(self, token: Any):
pass
"""释放令牌。"""
self._tokens.pop(id(token), None)
if not self._tokens:
self.released()
def isAcquired(self) -> bool:
return False
"""检查是否有令牌被持有。"""
return len(self._tokens) > 0
def acquired(self):
"""当第一个令牌被获取时调用。子类可重写。"""
pass
def released(self):
"""当所有令牌被释放时调用。子类可重写。"""
pass
def dump(self):
pass
"""转储令牌信息。"""
for tid, tag in self._tokens.items():
sys.stderr.write(f"[TokenWatcher] {self._tag}: token={tid}, tag={tag}\n")
class WorkSource(Stub):
@@ -1917,18 +2140,72 @@ class FileObserver(Stub):
super().__init__()
self._path = path
self._watching = False
self._thread = None
self._snapshot: Dict[str, float] = {}
def startWatching(self):
"""开始监听文件变化。使用轮询方式检测文件系统事件。"""
if self._watching:
return
self._watching = True
self._snapshot = self._take_snapshot()
self._thread = threading.Thread(target=self._poll_loop, daemon=True)
self._thread.start()
def _take_snapshot(self) -> Dict[str, float]:
"""获取当前目录的文件快照(文件名 -> 修改时间)。"""
snapshot: Dict[str, float] = {}
try:
if _os.path.isdir(self._path):
for name in _os.listdir(self._path):
full = _os.path.join(self._path, name)
try:
snapshot[name] = _os.path.getmtime(full)
except OSError:
pass
elif _os.path.exists(self._path):
try:
snapshot[self._path] = _os.path.getmtime(self._path)
except OSError:
pass
except OSError:
pass
return snapshot
def _poll_loop(self):
"""轮询检测文件变化并触发事件。"""
while self._watching:
_time.sleep(0.5)
try:
current = self._take_snapshot()
# 检测新建和修改
for name, mtime in current.items():
if name not in self._snapshot:
self.onEvent(FileObserver.CREATE, name)
elif mtime != self._snapshot[name]:
self.onEvent(FileObserver.MODIFY, name)
# 检测删除
for name in list(self._snapshot.keys()):
if name not in current:
self.onEvent(FileObserver.DELETE, name)
self._snapshot = current
except Exception:
pass
def stopWatching(self):
"""停止监听。"""
self._watching = False
if self._thread and self._thread.is_alive():
self._thread.join(timeout=1.0)
self._thread = None
def onEvent(self, event: int, path: Optional[str]):
"""文件事件回调,子类可重写。"""
pass
def finalize(self):
pass
"""清理资源。"""
self.stopWatching()
class FileUtils(Stub):
@@ -1985,7 +2262,35 @@ class FileUtils(Stub):
@staticmethod
def deleteOlderFiles(dir_: Any, min_count: int, min_age_ms: int):
pass
"""删除目录中较旧的文件,但保留至少 min_count 个文件。
min_age_ms 为文件的最小年龄(毫秒),低于此年龄的文件不会被删除。"""
try:
if not _os.path.isdir(dir_):
return
entries = []
for name in _os.listdir(dir_):
full = _os.path.join(dir_, name)
if _os.path.isfile(full):
try:
mtime = _os.path.getmtime(full)
entries.append((full, mtime))
except OSError:
pass
# 按修改时间排序(最新在前)
entries.sort(key=lambda x: x[1], reverse=True)
now = _time.time()
min_age_s = min_age_ms / 1000.0
# 保留最新的 min_count 个文件,删除超过 min_age 的旧文件
for i, (path, mtime) in enumerate(entries):
if i < min_count:
continue
if (now - mtime) >= min_age_s:
try:
_os.remove(path)
except OSError:
pass
except Exception:
pass
class PatternMatcher(Stub):