新增模块覆盖: 系统层 (14): system, security, print, opengl, renderscript, transition, test, service_notification, service_controls, service_quicksettings, service_wallpaper, service_autofill, service_dreams, service_vr 应用层 (13): app_admin, app_backup, app_job, app_usage, app_role, app_people, appwidget, companion, credentials, mtp, sip, telecom, speech 硬件媒体层 (15): hardware_display, hardware_fingerprint, hardware_usb, hardware_input, media_audiofx, media_browse, media_session, media_tv, media_midi, media_projection, uwb, se, view_autofill, view_textclassifier, view_translation 总计 94 个模块,75,342 行代码
592 lines
17 KiB
Python
592 lines
17 KiB
Python
"""
|
|
Android System 组件 — Os, StructStat, StructUtsname, OsConstants 等
|
|
方法签名完全对齐 Android SDK (android.system 包)
|
|
"""
|
|
|
|
import os as _os
|
|
import stat as _stat
|
|
import platform
|
|
import errno
|
|
from typing import Any, Dict, List, Optional, Tuple
|
|
|
|
from .._core import Stub, AndroidOnlyError
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# OsConstants
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class OsConstants(Stub):
|
|
"""OsConstants — 系统调用常量,映射自 os/stat 模块"""
|
|
|
|
# 文件访问常量
|
|
R_OK = _os.R_OK
|
|
W_OK = _os.W_OK
|
|
X_OK = _os.X_OK
|
|
F_OK = _os.F_OK
|
|
|
|
# 文件权限常量
|
|
S_IRWXU = _stat.S_IRWXU
|
|
S_IRUSR = _stat.S_IRUSR
|
|
S_IWUSR = _stat.S_IWUSR
|
|
S_IXUSR = _stat.S_IXUSR
|
|
S_IRWXG = _stat.S_IRWXG
|
|
S_IRGRP = _stat.S_IRGRP
|
|
S_IWGRP = _stat.S_IWGRP
|
|
S_IXGRP = _stat.S_IXGRP
|
|
S_IRWXO = _stat.S_IRWXO
|
|
S_IROTH = _stat.S_IROTH
|
|
S_IWOTH = _stat.S_IWOTH
|
|
S_IXOTH = _stat.S_IXOTH
|
|
S_ISUID = _stat.S_ISUID
|
|
S_ISGID = _stat.S_ISGID
|
|
S_ISVTX = _stat.S_ISVTX
|
|
|
|
# 文件类型常量
|
|
S_IFMT = _stat.S_IFMT
|
|
S_IFSOCK = _stat.S_IFSOCK
|
|
S_IFLNK = _stat.S_IFLNK
|
|
S_IFREG = _stat.S_IFREG
|
|
S_IFBLK = _stat.S_IFBLK
|
|
S_IFDIR = _stat.S_IFDIR
|
|
S_IFCHR = _stat.S_IFCHR
|
|
S_IFIFO = _stat.S_IFIFO
|
|
|
|
# 标准文件描述符
|
|
STDIN_FILENO = 0
|
|
STDOUT_FILENO = 1
|
|
STDERR_FILENO = 2
|
|
|
|
# 信号常量
|
|
SIGHUP = 1
|
|
SIGINT = 2
|
|
SIGQUIT = 3
|
|
SIGILL = 4
|
|
SIGTRAP = 5
|
|
SIGABRT = 6
|
|
SIGBUS = 7
|
|
SIGFPE = 8
|
|
SIGKILL = 9
|
|
SIGUSR1 = 10
|
|
SIGSEGV = 11
|
|
SIGUSR2 = 12
|
|
SIGPIPE = 13
|
|
SIGALRM = 14
|
|
SIGTERM = 15
|
|
SIGCHLD = 17
|
|
SIGCONT = 18
|
|
SIGSTOP = 19
|
|
SIGTSTP = 20
|
|
SIGTTIN = 21
|
|
SIGTTOU = 22
|
|
|
|
# errno 常量
|
|
EPERM = errno.EPERM
|
|
ENOENT = errno.ENOENT
|
|
ESRCH = errno.ESRCH
|
|
EINTR = errno.EINTR
|
|
EIO = errno.EIO
|
|
ENXIO = errno.ENXIO
|
|
E2BIG = errno.E2BIG
|
|
ENOEXEC = errno.ENOEXEC
|
|
EBADF = errno.EBADF
|
|
ECHILD = errno.ECHILD
|
|
EAGAIN = errno.EAGAIN
|
|
ENOMEM = errno.ENOMEM
|
|
EACCES = errno.EACCES
|
|
EFAULT = errno.EFAULT
|
|
ENOTBLK = errno.ENOTBLK
|
|
EBUSY = errno.EBUSY
|
|
EEXIST = errno.EEXIST
|
|
EXDEV = errno.EXDEV
|
|
ENODEV = errno.ENODEV
|
|
ENOTDIR = errno.ENOTDIR
|
|
EISDIR = errno.EISDIR
|
|
EINVAL = errno.EINVAL
|
|
ENFILE = errno.ENFILE
|
|
EMFILE = errno.EMFILE
|
|
ENOTTY = errno.ENOTTY
|
|
ETXTBSY = errno.ETXTBSY
|
|
EFBIG = errno.EFBIG
|
|
ENOSPC = errno.ENOSPC
|
|
ESPIPE = errno.ESPIPE
|
|
EROFS = errno.EROFS
|
|
EMLINK = errno.EMLINK
|
|
EPIPE = errno.EPIPE
|
|
EDOM = errno.EDOM
|
|
ERANGE = errno.ERANGE
|
|
EDEADLK = errno.EDEADLK
|
|
ENAMETOOLONG = errno.ENAMETOOLONG
|
|
ENOLCK = errno.ENOLCK
|
|
ENOSYS = errno.ENOSYS
|
|
ENOTEMPTY = errno.ENOTEMPTY
|
|
ELOOP = errno.ELOOP
|
|
ENOMSG = errno.ENOMSG
|
|
EIDRM = errno.EIDRM
|
|
ENOSTR = errno.ENOSTR
|
|
ENODATA = errno.ENODATA
|
|
ETIME = errno.ETIME
|
|
ENOSR = errno.ENOSR
|
|
EREMOTE = errno.EREMOTE
|
|
ENOLINK = errno.ENOLINK
|
|
EPROTO = errno.EPROTO
|
|
EMULTIHOP = errno.EMULTIHOP
|
|
EBADMSG = errno.EBADMSG
|
|
EOVERFLOW = errno.EOVERFLOW
|
|
EILSEQ = errno.EILSEQ
|
|
ENOTSOCK = errno.ENOTSOCK
|
|
EDESTADDRREQ = errno.EDESTADDRREQ
|
|
EMSGSIZE = errno.EMSGSIZE
|
|
EPROTOTYPE = errno.EPROTOTYPE
|
|
ENOPROTOOPT = errno.ENOPROTOOPT
|
|
EPROTONOSUPPORT = errno.EPROTONOSUPPORT
|
|
ESOCKTNOSUPPORT = errno.ESOCKTNOSUPPORT
|
|
EOPNOTSUPP = errno.EOPNOTSUPP
|
|
EPFNOSUPPORT = errno.EPFNOSUPPORT
|
|
EAFNOSUPPORT = errno.EAFNOSUPPORT
|
|
EADDRINUSE = errno.EADDRINUSE
|
|
EADDRNOTAVAIL = errno.EADDRNOTAVAIL
|
|
ENETDOWN = errno.ENETDOWN
|
|
ENETUNREACH = errno.ENETUNREACH
|
|
ENETRESET = errno.ENETRESET
|
|
ECONNABORTED = errno.ECONNABORTED
|
|
ECONNRESET = errno.ECONNRESET
|
|
ENOBUFS = errno.ENOBUFS
|
|
EISCONN = errno.EISCONN
|
|
ENOTCONN = errno.ENOTCONN
|
|
ESHUTDOWN = errno.ESHUTDOWN
|
|
ETOOMANYREFS = errno.ETOOMANYREFS
|
|
ETIMEDOUT = errno.ETIMEDOUT
|
|
ECONNREFUSED = errno.ECONNREFUSED
|
|
EHOSTDOWN = errno.EHOSTDOWN
|
|
EHOSTUNREACH = errno.EHOSTUNREACH
|
|
EALREADY = errno.EALREADY
|
|
EINPROGRESS = errno.EINPROGRESS
|
|
ESTALE = errno.ESTALE
|
|
EUCLEAN = errno.EUCLEAN
|
|
ENOTNAM = errno.ENOTNAM
|
|
ENAVAIL = errno.ENAVAIL
|
|
EISNAM = errno.EISNAM
|
|
EREMOTEIO = errno.EREMOTEIO
|
|
EDQUOT = errno.EDQUOT
|
|
ENOMEDIUM = errno.ENOMEDIUM
|
|
EMEDIUMTYPE = errno.EMEDIUMTYPE
|
|
ECANCELED = errno.ECANCELED
|
|
ENOKEY = errno.ENOKEY
|
|
EKEYEXPIRED = errno.EKEYEXPIRED
|
|
EKEYREVOKED = errno.EKEYREVOKED
|
|
EKEYREJECTED = errno.EKEYREJECTED
|
|
EOWNERDEAD = errno.EOWNERDEAD
|
|
ENOTRECOVERABLE = errno.ENOTRECOVERABLE
|
|
ERFKILL = errno.ERFKILL
|
|
EHWPOISON = getattr(errno, 'EHWPOISON', 1001)
|
|
|
|
def __init__(self):
|
|
super().__init__()
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# StructStat
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class StructStat(Stub):
|
|
"""StructStat — stat() 返回的文件状态结构体"""
|
|
|
|
def __init__(self, st_mode: int = 0, st_ino: int = 0, st_dev: int = 0,
|
|
st_nlink: int = 0, st_uid: int = 0, st_gid: int = 0,
|
|
st_size: int = 0, st_atime: int = 0, st_mtime: int = 0,
|
|
st_ctime: int = 0, st_blksize: int = 4096,
|
|
st_blocks: int = 0, st_rdev: int = 0):
|
|
super().__init__()
|
|
self.st_mode = st_mode
|
|
self.st_ino = st_ino
|
|
self.st_dev = st_dev
|
|
self.st_nlink = st_nlink
|
|
self.st_uid = st_uid
|
|
self.st_gid = st_gid
|
|
self.st_size = st_size
|
|
self.st_atime = st_atime
|
|
self.st_mtime = st_mtime
|
|
self.st_ctime = st_ctime
|
|
self.st_blksize = st_blksize
|
|
self.st_blocks = st_blocks
|
|
self.st_rdev = st_rdev
|
|
self.st_atime_ns = st_atime * 1_000_000_000
|
|
self.st_mtime_ns = st_mtime * 1_000_000_000
|
|
self.st_ctime_ns = st_ctime * 1_000_000_000
|
|
|
|
@staticmethod
|
|
def from_os_stat(st: _os.stat_result) -> "StructStat":
|
|
"""从 Python os.stat_result 创建 StructStat"""
|
|
return StructStat(
|
|
st_mode=st.st_mode,
|
|
st_ino=st.st_ino,
|
|
st_dev=st.st_dev,
|
|
st_nlink=st.st_nlink,
|
|
st_uid=st.st_uid,
|
|
st_gid=st.st_gid,
|
|
st_size=st.st_size,
|
|
st_atime=int(st.st_atime),
|
|
st_mtime=int(st.st_mtime),
|
|
st_ctime=int(st.st_ctime),
|
|
st_blksize=st.st_blksize,
|
|
st_blocks=st.st_blocks,
|
|
st_rdev=st.st_rdev,
|
|
)
|
|
|
|
def toString(self) -> str:
|
|
return (f"StructStat(st_mode={oct(self.st_mode)}, st_size={self.st_size}, "
|
|
f"st_mtime={self.st_mtime}, st_uid={self.st_uid}, st_gid={self.st_gid})")
|
|
|
|
def hashCode(self) -> int:
|
|
return hash((self.st_dev, self.st_ino, self.st_mode)) & 0x7FFFFFFF
|
|
|
|
def equals(self, other) -> bool:
|
|
if not isinstance(other, StructStat):
|
|
return False
|
|
return (self.st_dev == other.st_dev and self.st_ino == other.st_ino
|
|
and self.st_mode == other.st_mode and self.st_size == other.st_size)
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# StructUtsname
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class StructUtsname(Stub):
|
|
"""StructUtsname — uname() 返回的系统信息结构体"""
|
|
|
|
def __init__(self, sysname: str = "", nodename: str = "",
|
|
release: str = "", version: str = "", machine: str = ""):
|
|
super().__init__()
|
|
self.sysname = sysname or platform.system()
|
|
self.nodename = nodename or platform.node()
|
|
self.release = release or platform.release()
|
|
self.version = version or platform.version()
|
|
self.machine = machine or platform.machine()
|
|
|
|
@staticmethod
|
|
def from_platform() -> "StructUtsname":
|
|
"""从 Python platform 模块创建 StructUtsname"""
|
|
uname = platform.uname()
|
|
return StructUtsname(
|
|
sysname=uname.system,
|
|
nodename=uname.node,
|
|
release=uname.release,
|
|
version=uname.version,
|
|
machine=uname.machine,
|
|
)
|
|
|
|
def toString(self) -> str:
|
|
return (f"StructUtsname(sysname={self.sysname}, nodename={self.nodename}, "
|
|
f"release={self.release}, version={self.version}, machine={self.machine})")
|
|
|
|
def hashCode(self) -> int:
|
|
return hash((self.sysname, self.nodename, self.release)) & 0x7FFFFFFF
|
|
|
|
def equals(self, other) -> bool:
|
|
if not isinstance(other, StructUtsname):
|
|
return False
|
|
return (self.sysname == other.sysname and self.nodename == other.nodename
|
|
and self.release == other.release)
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# Os
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class Os(Stub):
|
|
"""Os — 系统调用包装器,代理到 Python os 模块"""
|
|
|
|
def __init__(self):
|
|
super().__init__()
|
|
|
|
# ── 文件操作 ──
|
|
|
|
@staticmethod
|
|
def stat(path: str) -> StructStat:
|
|
"""获取文件状态"""
|
|
st = _os.stat(path)
|
|
return StructStat.from_os_stat(st)
|
|
|
|
@staticmethod
|
|
def lstat(path: str) -> StructStat:
|
|
"""获取符号链接自身状态"""
|
|
st = _os.lstat(path)
|
|
return StructStat.from_os_stat(st)
|
|
|
|
@staticmethod
|
|
def chmod(path: str, mode: int):
|
|
"""修改文件权限"""
|
|
_os.chmod(path, mode)
|
|
|
|
@staticmethod
|
|
def chown(path: str, uid: int, gid: int):
|
|
"""修改文件所有者"""
|
|
_os.chown(path, uid, gid)
|
|
|
|
@staticmethod
|
|
def link(oldpath: str, newpath: str):
|
|
"""创建硬链接"""
|
|
_os.link(oldpath, newpath)
|
|
|
|
@staticmethod
|
|
def symlink(target: str, linkpath: str):
|
|
"""创建符号链接"""
|
|
_os.symlink(target, linkpath)
|
|
|
|
@staticmethod
|
|
def readlink(path: str) -> str:
|
|
"""读取符号链接目标"""
|
|
return _os.readlink(path)
|
|
|
|
@staticmethod
|
|
def unlink(pathname: str):
|
|
"""删除文件(解除链接)"""
|
|
_os.unlink(pathname)
|
|
|
|
@staticmethod
|
|
def remove(path: str):
|
|
"""删除文件"""
|
|
_os.remove(path)
|
|
|
|
@staticmethod
|
|
def rename(oldpath: str, newpath: str):
|
|
"""重命名文件"""
|
|
_os.rename(oldpath, newpath)
|
|
|
|
@staticmethod
|
|
def mkdir(path: str, mode: int = 0o777):
|
|
"""创建目录"""
|
|
_os.mkdir(path, mode)
|
|
|
|
@staticmethod
|
|
def rmdir(path: str):
|
|
"""删除空目录"""
|
|
_os.rmdir(path)
|
|
|
|
@staticmethod
|
|
def listdir(path: str) -> List[str]:
|
|
"""列出目录内容"""
|
|
return _os.listdir(path)
|
|
|
|
@staticmethod
|
|
def truncate(path: str, length: int):
|
|
"""截断文件到指定长度"""
|
|
with open(path, 'ab') as f:
|
|
f.truncate(length)
|
|
|
|
@staticmethod
|
|
def access(path: str, mode: int) -> bool:
|
|
"""检查文件访问权限"""
|
|
return _os.access(path, mode)
|
|
|
|
# ── 文件描述符操作 ──
|
|
|
|
@staticmethod
|
|
def dup(oldfd: int) -> int:
|
|
"""复制文件描述符"""
|
|
return _os.dup(oldfd)
|
|
|
|
@staticmethod
|
|
def dup2(oldfd: int, newfd: int):
|
|
"""复制文件描述符到指定值"""
|
|
_os.dup2(oldfd, newfd)
|
|
|
|
@staticmethod
|
|
def close(fd: int):
|
|
"""关闭文件描述符"""
|
|
_os.close(fd)
|
|
|
|
@staticmethod
|
|
def read(fd: int, count: int) -> bytes:
|
|
"""从文件描述符读取"""
|
|
return _os.read(fd, count)
|
|
|
|
@staticmethod
|
|
def write(fd: int, data: bytes) -> int:
|
|
"""写入文件描述符"""
|
|
return _os.write(fd, data)
|
|
|
|
@staticmethod
|
|
def lseek(fd: int, offset: int, whence: int) -> int:
|
|
"""移动文件读写位置"""
|
|
return _os.lseek(fd, offset, whence)
|
|
|
|
@staticmethod
|
|
def fsync(fd: int):
|
|
"""同步文件描述符"""
|
|
_os.fsync(fd)
|
|
|
|
@staticmethod
|
|
def fstat(fd: int) -> StructStat:
|
|
"""获取文件描述符对应文件状态"""
|
|
st = _os.fstat(fd)
|
|
return StructStat.from_os_stat(st)
|
|
|
|
@staticmethod
|
|
def isatty(fd: int) -> bool:
|
|
"""判断文件描述符是否为终端"""
|
|
return _os.isatty(fd)
|
|
|
|
# ── 进程相关 ──
|
|
|
|
@staticmethod
|
|
def getpid() -> int:
|
|
"""获取当前进程 ID"""
|
|
return _os.getpid()
|
|
|
|
@staticmethod
|
|
def getppid() -> int:
|
|
"""获取父进程 ID"""
|
|
return _os.getppid()
|
|
|
|
@staticmethod
|
|
def getuid() -> int:
|
|
"""获取当前用户 ID"""
|
|
return _os.getuid()
|
|
|
|
@staticmethod
|
|
def getgid() -> int:
|
|
"""获取当前组 ID"""
|
|
return _os.getgid()
|
|
|
|
@staticmethod
|
|
def geteuid() -> int:
|
|
"""获取有效用户 ID"""
|
|
return _os.geteuid()
|
|
|
|
@staticmethod
|
|
def getegid() -> int:
|
|
"""获取有效组 ID"""
|
|
return _os.getegid()
|
|
|
|
@staticmethod
|
|
def setuid(uid: int):
|
|
"""设置用户 ID"""
|
|
_os.setuid(uid)
|
|
|
|
@staticmethod
|
|
def setgid(gid: int):
|
|
"""设置组 ID"""
|
|
_os.setgid(gid)
|
|
|
|
@staticmethod
|
|
def setsid() -> int:
|
|
"""创建新会话"""
|
|
return _os.setsid()
|
|
|
|
@staticmethod
|
|
def umask(mask: int) -> int:
|
|
"""设置文件创建掩码"""
|
|
return _os.umask(mask)
|
|
|
|
@staticmethod
|
|
def kill(pid: int, sig: int):
|
|
"""发送信号给进程"""
|
|
_os.kill(pid, sig)
|
|
|
|
@staticmethod
|
|
def getenv(name: str, default: Optional[str] = None) -> Optional[str]:
|
|
"""获取环境变量"""
|
|
return _os.environ.get(name, default)
|
|
|
|
@staticmethod
|
|
def setenv(name: str, value: str, overwrite: bool = True):
|
|
"""设置环境变量"""
|
|
if overwrite or name not in _os.environ:
|
|
_os.environ[name] = value
|
|
|
|
@staticmethod
|
|
def unsetenv(name: str):
|
|
"""删除环境变量"""
|
|
_os.environ.pop(name, None)
|
|
|
|
@staticmethod
|
|
def environ() -> Dict[str, str]:
|
|
"""获取环境变量字典"""
|
|
return dict(_os.environ)
|
|
|
|
# ── 系统信息 ──
|
|
|
|
@staticmethod
|
|
def uname() -> StructUtsname:
|
|
"""获取系统信息"""
|
|
return StructUtsname.from_platform()
|
|
|
|
@staticmethod
|
|
def sysconf(name: str) -> int:
|
|
"""获取系统配置值"""
|
|
conf_names = {
|
|
"SC_CLK_TCK": 100,
|
|
"SC_PAGE_SIZE": 4096,
|
|
"SC_NPROCESSORS_CONF": _os.cpu_count() or 1,
|
|
"SC_NPROCESSORS_ONLN": _os.cpu_count() or 1,
|
|
}
|
|
return conf_names.get(name, -1)
|
|
|
|
@staticmethod
|
|
def getpagesize() -> int:
|
|
"""获取内存页大小"""
|
|
return 4096
|
|
|
|
@staticmethod
|
|
def getloadavg() -> List[float]:
|
|
"""获取系统负载平均值"""
|
|
try:
|
|
return list(_os.getloadavg())
|
|
except AttributeError:
|
|
return [0.0, 0.0, 0.0]
|
|
|
|
# ── 管道与 I/O ──
|
|
|
|
@staticmethod
|
|
def pipe() -> Tuple[int, int]:
|
|
"""创建管道"""
|
|
return _os.pipe()
|
|
|
|
@staticmethod
|
|
def mkfifo(path: str, mode: int = 0o666):
|
|
"""创建命名管道 (FIFO)"""
|
|
_os.mkfifo(path, mode)
|
|
|
|
@staticmethod
|
|
def tmpfile() -> str:
|
|
"""创建临时文件路径"""
|
|
import tempfile
|
|
return tempfile.mktemp()
|
|
|
|
# ── 时间 ──
|
|
|
|
@staticmethod
|
|
def time() -> int:
|
|
"""获取当前时间戳 (秒)"""
|
|
import time
|
|
return int(time.time())
|
|
|
|
# ── 其他 ──
|
|
|
|
@staticmethod
|
|
def strerror(errno: int) -> str:
|
|
"""将错误码转为错误描述"""
|
|
return _os.strerror(errno)
|
|
|
|
def toString(self) -> str:
|
|
return f"Os(sysname={platform.system()}, release={platform.release()})"
|
|
|
|
def hashCode(self) -> int:
|
|
return hash("android.system.Os") & 0x7FFFFFFF
|
|
|
|
def equals(self, other) -> bool:
|
|
return isinstance(other, Os)
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# __all__
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
__all__ = [
|
|
"Os",
|
|
"StructStat",
|
|
"StructUtsname",
|
|
"OsConstants",
|
|
] |