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:
1 parent
39b1da37c9
commit
4235f8692c
13 files changed
+2248
-163
No files matched your search
@@ -12,10 +12,16 @@ from .._core import Stub, AndroidOnlyError, android_context, HAS_PIL
|
||||
|
||||
# Linux 真实实现导入
|
||||
try:
|
||||
from .._linux_impl import IS_LINUX, LinuxBluetooth, LinuxSensors, HAS_BLUETOOTHCTL
|
||||
from .._linux_impl import IS_LINUX, LinuxBluetooth, LinuxSensors, HAS_BLUETOOTHCTL, LinuxPower
|
||||
_USE_LINUX = IS_LINUX
|
||||
except ImportError:
|
||||
_USE_LINUX = False
|
||||
try:
|
||||
from .._linux_impl import IS_LINUX, LinuxBluetooth, LinuxSensors, HAS_BLUETOOTHCTL
|
||||
_USE_LINUX = IS_LINUX
|
||||
LinuxPower = None
|
||||
except ImportError:
|
||||
_USE_LINUX = False
|
||||
LinuxPower = None
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
@@ -379,18 +385,56 @@ class SensorManager(Stub):
|
||||
@staticmethod
|
||||
def getRotationMatrix(R: List[float], I: List[float],
|
||||
gravity: List[float], geomagnetic: List[float]) -> bool:
|
||||
"""根据重力和地磁向量计算旋转矩阵 R 和倾斜矩阵 I。
|
||||
算法对齐 Android SensorManager.getRotationMatrix。"""
|
||||
if len(R) < 9:
|
||||
R.extend([0] * (9 - len(R)))
|
||||
if len(R) >= 9:
|
||||
R[0] = 1.0
|
||||
R[1] = 0.0
|
||||
R[2] = 0.0
|
||||
R[3] = 0.0
|
||||
R[4] = 1.0
|
||||
R[5] = 0.0
|
||||
R[6] = 0.0
|
||||
R[7] = 0.0
|
||||
R[8] = 1.0
|
||||
R.extend([0.0] * (9 - len(R)))
|
||||
gx, gy, gz = gravity[0], gravity[1], gravity[2]
|
||||
mx, my, mz = geomagnetic[0], geomagnetic[1], geomagnetic[2]
|
||||
# 归一化重力向量 -> H
|
||||
g_len = math.sqrt(gx * gx + gy * gy + gz * gz)
|
||||
if g_len < 1e-10:
|
||||
return False
|
||||
hx = gx / g_len
|
||||
hy = gy / g_len
|
||||
hz = gz / g_len
|
||||
# 叉积 A = H x M (东方向)
|
||||
ax = hy * mz - hz * my
|
||||
ay = hz * mx - hx * mz
|
||||
az = hx * my - hy * mx
|
||||
a_len = math.sqrt(ax * ax + ay * ay + az * az)
|
||||
if a_len < 1e-10:
|
||||
return False
|
||||
ax /= a_len
|
||||
ay /= a_len
|
||||
az /= a_len
|
||||
# 重新计算 M = A x H
|
||||
ex = ay * hz - az * hy
|
||||
ey = az * hx - ax * hz
|
||||
ez = ax * hy - ay * hx
|
||||
# 填充旋转矩阵 R (列优先,Android 格式)
|
||||
R[0] = ax
|
||||
R[1] = ay
|
||||
R[2] = az
|
||||
R[3] = ex
|
||||
R[4] = ey
|
||||
R[5] = ez
|
||||
R[6] = hx
|
||||
R[7] = hy
|
||||
R[8] = hz
|
||||
# 填充倾斜矩阵 I
|
||||
if I is not None and len(I) >= 9:
|
||||
inv_h = 1.0 / g_len
|
||||
inv_m = 1.0 / math.sqrt(mx * mx + my * my + mz * mz) if (mx * mx + my * my + mz * mz) > 0 else 0
|
||||
I[0] = inv_h * hx
|
||||
I[1] = inv_h * hy
|
||||
I[2] = inv_h * hz
|
||||
I[3] = inv_m * mx
|
||||
I[4] = inv_m * my
|
||||
I[5] = inv_m * mz
|
||||
I[6] = inv_h * ex
|
||||
I[7] = inv_h * ey
|
||||
I[8] = inv_h * ez
|
||||
return True
|
||||
|
||||
@staticmethod
|
||||
@@ -399,17 +443,69 @@ class SensorManager(Stub):
|
||||
|
||||
@staticmethod
|
||||
def getInclination(I: List[float]) -> float:
|
||||
"""根据倾斜矩阵 I 计算地磁倾角(弧度)。"""
|
||||
if len(I) >= 9:
|
||||
# I[5] = cos(el), I[2] = sin(el)
|
||||
# 倾角 = atan2(I[2], I[5])
|
||||
return math.atan2(I[2], I[5])
|
||||
return 0.0
|
||||
|
||||
@staticmethod
|
||||
def remapCoordinateSystem(inR: List[float], X: int, Y: int,
|
||||
outR: List[float]) -> bool:
|
||||
if len(inR) >= 9 and len(outR) >= 9:
|
||||
for i in range(9):
|
||||
outR[i] = inR[i]
|
||||
"""根据指定的 X/Y 轴重映射坐标系。"""
|
||||
if len(inR) < 9 or len(outR) < 9:
|
||||
return False
|
||||
# Android 轴常量
|
||||
AXIS_X = 1
|
||||
AXIS_Y = 2
|
||||
AXIS_Z = 3
|
||||
AXIS_MINUS_X = -1
|
||||
AXIS_MINUS_Y = -2
|
||||
AXIS_MINUS_Z = -3
|
||||
# 将轴常量映射到列索引和符号
|
||||
axis_map = {
|
||||
AXIS_X: (0, 1), AXIS_Y: (1, 1), AXIS_Z: (2, 1),
|
||||
AXIS_MINUS_X: (0, -1), AXIS_MINUS_Y: (1, -1), AXIS_MINUS_Z: (2, -1),
|
||||
}
|
||||
if X not in axis_map or Y not in axis_map:
|
||||
return False
|
||||
x_col, x_sign = axis_map[X]
|
||||
y_col, y_sign = axis_map[Y]
|
||||
# Z = X x Y
|
||||
z_col = 3 - x_col - y_col
|
||||
z_sign = x_sign * y_sign
|
||||
# 如果 X 和 Y 不正交
|
||||
if abs(x_col - y_col) != 1 and not (x_col == 0 and y_col == 2) and not (x_col == 2 and y_col == 0):
|
||||
z_sign = -z_sign
|
||||
# 填充输出矩阵(列优先)
|
||||
for row in range(3):
|
||||
outR[row * 3 + 0] = inR[row * 3 + x_col] * x_sign
|
||||
outR[row * 3 + 1] = inR[row * 3 + y_col] * y_sign
|
||||
outR[row * 3 + 2] = inR[row * 3 + z_col] * z_sign
|
||||
return True
|
||||
|
||||
def getDeviceId(self) -> str:
|
||||
"""返回传感器设备 ID。尝试从 /sys 读取真实设备标识。"""
|
||||
import os as _os
|
||||
# 尝试从 /sys/class/sensor 读取
|
||||
try:
|
||||
base = "/sys/class/sensor"
|
||||
if _os.path.isdir(base):
|
||||
names = _os.listdir(base)
|
||||
if names:
|
||||
return names[0]
|
||||
except (OSError, IOError):
|
||||
pass
|
||||
# 尝试从 /sys/bus/iio/devices 读取
|
||||
try:
|
||||
base = "/sys/bus/iio/devices"
|
||||
if _os.path.isdir(base):
|
||||
names = _os.listdir(base)
|
||||
if names:
|
||||
return names[0]
|
||||
except (OSError, IOError):
|
||||
pass
|
||||
return "sensor_hub_0"
|
||||
|
||||
|
||||
@@ -552,6 +648,29 @@ class BatteryManager(Stub):
|
||||
super().__init__()
|
||||
|
||||
def getIntProperty(self, id: int) -> int:
|
||||
"""返回电池整型属性。优先使用 LinuxPower 读取真实数据。"""
|
||||
if _USE_LINUX and LinuxPower is not None:
|
||||
try:
|
||||
info = LinuxPower.get_battery_info() or {}
|
||||
if id == BatteryManager.BATTERY_PROPERTY_CAPACITY:
|
||||
level = info.get("level", -1)
|
||||
return int(level) if isinstance(level, (int, float)) and level >= 0 else -1
|
||||
if id == BatteryManager.BATTERY_PROPERTY_STATUS:
|
||||
status_map = {
|
||||
"charging": BatteryManager.BATTERY_STATUS_CHARGING,
|
||||
"discharging": BatteryManager.BATTERY_STATUS_DISCHARGING,
|
||||
"not charging": BatteryManager.BATTERY_STATUS_NOT_CHARGING,
|
||||
"full": BatteryManager.BATTERY_STATUS_FULL,
|
||||
"unknown": BatteryManager.BATTERY_STATUS_UNKNOWN,
|
||||
}
|
||||
return status_map.get(str(info.get("status", "unknown")).lower(),
|
||||
BatteryManager.BATTERY_STATUS_UNKNOWN)
|
||||
if id == BatteryManager.BATTERY_PROPERTY_CHARGE_COUNTER:
|
||||
voltage = info.get("voltage", 0)
|
||||
return int(voltage * 1000) if isinstance(voltage, (int, float)) else 0
|
||||
except Exception:
|
||||
pass
|
||||
# 回退到默认值
|
||||
id_values = {
|
||||
BatteryManager.BATTERY_PROPERTY_CHARGE_COUNTER: 3500,
|
||||
BatteryManager.BATTERY_PROPERTY_CAPACITY: 85,
|
||||
@@ -560,7 +679,19 @@ class BatteryManager(Stub):
|
||||
return id_values.get(id, 0)
|
||||
|
||||
def getLongProperty(self, id: int) -> int:
|
||||
return 0
|
||||
"""返回电池长整型属性。优先使用 LinuxPower 读取真实数据。"""
|
||||
if _USE_LINUX and LinuxPower is not None:
|
||||
try:
|
||||
info = LinuxPower.get_battery_info() or {}
|
||||
if id == BatteryManager.BATTERY_PROPERTY_CURRENT_NOW:
|
||||
current = info.get("current_now", 0)
|
||||
return int(current) if isinstance(current, (int, float)) else 0
|
||||
if id == BatteryManager.BATTERY_PROPERTY_ENERGY_COUNTER:
|
||||
voltage = info.get("voltage", 0)
|
||||
return int(voltage * 3600000) if isinstance(voltage, (int, float)) else 0
|
||||
except Exception:
|
||||
pass
|
||||
return self.getIntProperty(id)
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
|
||||
Reference in new issue
Block a user