新增 _linux_impl.py (800+行): - LinuxNetwork: 真实IP/接口/DNS/网关/MAC (ip命令+/proc/net) - LinuxBluetooth: 真实蓝牙状态/扫描/配对/连接 (bluetoothctl) - LinuxSensors: 真实温度/CPU频率/风扇 (/sys/class/hwmon) - LinuxAudio: 真实音量控制/静音 (amixer) - LinuxClipboard: 真实剪贴板读写 (xclip+tkinter回退) - LinuxPower: 真实CPU/内存/电池 (psutil+/sys/class/power_supply) - LinuxLocation: 真实IP地理定位 (ip-api.com) - LinuxNotify: 真实桌面通知 (notify-send) - LinuxDisplay: 真实屏幕尺寸/截屏/鼠标位置 (xdotool+X11) - LinuxUIAutomation: 真实点击/输入/按键/滚动 (xdotool) - LinuxCamera: 真实摄像头拍照 (opencv/V4L2) - LinuxProcess: 真实进程列表/系统信息/应用管理 (psutil+/proc) - LinuxShell: 真实命令执行 (subprocess) 改造10+核心类使用Linux真实实现: - BluetoothAdapter/SensorManager/AudioManager - ConnectivityManager/WifiManager/TelephonyManager - LocationManager/PowerManager/BatteryManager/Build - ActivityManager/Activity/Toast/Display/ClipboardManager - NotificationManager 15项真实行为测试全部通过: - 真实IP: 10.60.218.244 - 真实位置: 北京 39.9042, 116.407 - 真实主机名: work-41-vci-g427c - 真实内核: 5.15.120.byteatom-ck.14 - 真实内存: 1.8GB/3.8GB - 真实进程列表
1773 lines
64 KiB
Python
1773 lines
64 KiB
Python
"""
|
|
Android System Manager API — 所有剩余系统 Manager 类集合
|
|
方法签名完全对齐 Android SDK
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
import sys
|
|
import time
|
|
import json
|
|
import random
|
|
import socket
|
|
import uuid
|
|
import threading
|
|
from datetime import datetime, timedelta
|
|
from typing import Any, Dict, List, Optional, Set, Tuple, Callable, BinaryIO
|
|
|
|
from .._core import Stub, AndroidOnlyError, _app_data_dir, _sdcard_root
|
|
|
|
from ..java.lang import RuntimeException
|
|
|
|
# Linux 真实实现导入
|
|
try:
|
|
from .._linux_impl import IS_LINUX, LinuxNetwork, HAS_IP
|
|
_USE_LINUX = IS_LINUX
|
|
except ImportError:
|
|
_USE_LINUX = False
|
|
|
|
IllegalArgumentException = type("IllegalArgumentException", (RuntimeException,), {})
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# 全局常量
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
INVALID_ID = -1
|
|
MATCH_ALL = -1
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# AccessibilityManager
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class AccessibilityManager(Stub):
|
|
"""AccessibilityManager — 无障碍管理器 (桌面存根)"""
|
|
|
|
FLAG_CONTENT_CONTROLS = 0x00000001
|
|
FLAG_CONTENT_ICONS = 0x00000002
|
|
FLAG_CONTENT_TEXT = 0x00000004
|
|
FLAG_CONTENT_CONTENT_DESCRIPTION = 0x00000008
|
|
|
|
def __init__(self, context: Any = None):
|
|
super().__init__()
|
|
self._context = context
|
|
self._enabled = False
|
|
self._touch_exploration_enabled = False
|
|
self._high_text_contrast_enabled = False
|
|
self._animator_duration_scale = 1.0
|
|
self._display_magnification_enabled = False
|
|
self._accessibility_volume = 0
|
|
self._speech_rate = 1.0
|
|
self._listeners: List[Any] = []
|
|
|
|
def isEnabled(self) -> bool:
|
|
return self._enabled
|
|
|
|
def addAccessibilityStateChangeListener(self, listener: Any) -> bool:
|
|
if listener not in self._listeners:
|
|
self._listeners.append(listener)
|
|
return True
|
|
|
|
def removeAccessibilityStateChangeListener(self, listener: Any) -> bool:
|
|
if listener in self._listeners:
|
|
self._listeners.remove(listener)
|
|
return True
|
|
|
|
def isTouchExplorationEnabled(self) -> bool:
|
|
return self._touch_exploration_enabled
|
|
|
|
def isHighTextContrastEnabled(self) -> bool:
|
|
return self._high_text_contrast_enabled
|
|
|
|
def getAccessibilityServiceList(self) -> List[Any]:
|
|
return []
|
|
|
|
def addTouchExplorationStateChangeListener(self, listener: Any) -> None:
|
|
pass
|
|
|
|
def removeTouchExplorationStateChangeListener(self, listener: Any) -> None:
|
|
pass
|
|
|
|
def sendAccessibilityEvent(self, event: Any) -> None:
|
|
pass
|
|
|
|
def interrupt(self) -> None:
|
|
pass
|
|
|
|
def getEnabledAccessibilityServiceList(self, feedbackTypeFlags: int) -> List[Any]:
|
|
return []
|
|
|
|
def getInstalledAccessibilityServiceList(self) -> List[Any]:
|
|
return []
|
|
|
|
def toString(self) -> str:
|
|
return f"AccessibilityManager(enabled={self._enabled})"
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# AccountManager (扩展)
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class AccountManager(Stub):
|
|
"""AccountManager — 账户管理器 (扩展)"""
|
|
|
|
KEY_ACCOUNTS = "accounts"
|
|
KEY_ACCOUNT_NAME = "accountName"
|
|
KEY_ACCOUNT_TYPE = "accountType"
|
|
KEY_AUTHTOKEN = "authtoken"
|
|
KEY_AUTH_FAILED_MESSAGE = "authFailedMessage"
|
|
KEY_AUTH_TOKEN_LABEL = "authTokenLabelKey"
|
|
KEY_BOOLEAN_RESULT = "booleanResult"
|
|
KEY_ERROR_CODE = "errorCode"
|
|
KEY_ERROR_MESSAGE = "errorMessage"
|
|
KEY_INTENT = "intent"
|
|
KEY_PASSWORD = "password"
|
|
KEY_USERDATA = "userdata"
|
|
KEY_CUSTOM_TOKEN_EXPIRY = "customTokenExpiry"
|
|
KEY_ACCOUNT_ACCESS_ID = "accountAccessId"
|
|
|
|
ERROR_CODE_NETWORK_ERROR = 1
|
|
ERROR_CODE_UNSUPPORTED_OPERATION = 2
|
|
ERROR_CODE_INVALID_RESPONSE = 3
|
|
ERROR_CODE_REMOTE_EXCEPTION = 4
|
|
ERROR_CODE_MANAGEMENT_DISABLED = 5
|
|
ERROR_CODE_BAD_ARGUMENTS = 6
|
|
ERROR_CODE_BAD_REQUEST = 7
|
|
ERROR_CODE_DENIED = 8
|
|
ERROR_CODE_CANCELED = 9
|
|
ERROR_CODE_INVALID_CREDENTIALS = 10
|
|
ERROR_CODE_SESSION_EXPIRED = 11
|
|
ERROR_CODE_USER_RESTRICTION = 12
|
|
|
|
_instance: Optional["AccountManager"] = None
|
|
|
|
def __init__(self, context: Any = None):
|
|
super().__init__()
|
|
self._context = context
|
|
self._accounts: List[Any] = []
|
|
self._auth_tokens: Dict[str, str] = {}
|
|
self._user_data: Dict[str, Dict[str, str]] = {}
|
|
self._password_data: Dict[str, str] = {}
|
|
self._account_visibility: Dict[str, bool] = {}
|
|
self._lock = threading.Lock()
|
|
|
|
@staticmethod
|
|
def get(context: Any) -> "AccountManager":
|
|
if AccountManager._instance is None:
|
|
AccountManager._instance = AccountManager(context)
|
|
return AccountManager._instance
|
|
|
|
def getAccounts(self) -> List[Any]:
|
|
with self._lock:
|
|
return list(self._accounts)
|
|
|
|
def getAccountsByType(self, type_: str) -> List[Any]:
|
|
with self._lock:
|
|
return [a for a in self._accounts if getattr(a, "type", None) == type_]
|
|
|
|
def addAccountExplicitly(self, account: Any, password: Optional[str], userdata: Optional[Dict]) -> bool:
|
|
with self._lock:
|
|
if account not in self._accounts:
|
|
self._accounts.append(account)
|
|
name = getattr(account, "name", str(account))
|
|
if password is not None:
|
|
self._password_data[name] = password
|
|
if userdata:
|
|
self._user_data[name] = dict(userdata)
|
|
return True
|
|
return False
|
|
|
|
def removeAccountExplicitly(self, account: Any) -> bool:
|
|
with self._lock:
|
|
if account in self._accounts:
|
|
self._accounts.remove(account)
|
|
name = getattr(account, "name", str(account))
|
|
self._password_data.pop(name, None)
|
|
self._user_data.pop(name, None)
|
|
return True
|
|
return False
|
|
|
|
def getUserData(self, account: Any, key: str) -> Optional[str]:
|
|
with self._lock:
|
|
name = getattr(account, "name", str(account))
|
|
return self._user_data.get(name, {}).get(key)
|
|
|
|
def setUserData(self, account: Any, key: str, value: str) -> None:
|
|
with self._lock:
|
|
name = getattr(account, "name", str(account))
|
|
if name not in self._user_data:
|
|
self._user_data[name] = {}
|
|
self._user_data[name][key] = value
|
|
|
|
def getPassword(self, account: Any) -> Optional[str]:
|
|
with self._lock:
|
|
name = getattr(account, "name", str(account))
|
|
return self._password_data.get(name)
|
|
|
|
def setPassword(self, account: Any, password: str) -> None:
|
|
with self._lock:
|
|
name = getattr(account, "name", str(account))
|
|
self._password_data[name] = password
|
|
|
|
def clearPassword(self, account: Any) -> None:
|
|
with self._lock:
|
|
name = getattr(account, "name", str(account))
|
|
self._password_data.pop(name, None)
|
|
|
|
def getAuthToken(self, account: Any, authTokenType: str) -> Optional[str]:
|
|
with self._lock:
|
|
name = getattr(account, "name", str(account))
|
|
return self._auth_tokens.get(f"{name}:{authTokenType}")
|
|
|
|
def setAuthToken(self, account: Any, authTokenType: str, authToken: str) -> None:
|
|
with self._lock:
|
|
name = getattr(account, "name", str(account))
|
|
self._auth_tokens[f"{name}:{authTokenType}"] = authToken
|
|
|
|
def invalidateAuthToken(self, accountType: str, authToken: str) -> None:
|
|
with self._lock:
|
|
to_remove = [k for k, v in self._auth_tokens.items() if v == authToken]
|
|
for k in to_remove:
|
|
del self._auth_tokens[k]
|
|
|
|
def hasFeatures(self, account: Any, features: List[str], callback: Any, handler: Any = None) -> None:
|
|
pass
|
|
|
|
def getAccountVisibility(self, account: Any, packageName: str) -> int:
|
|
return 1
|
|
|
|
def toString(self) -> str:
|
|
return f"AccountManager(accounts={len(self._accounts)})"
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# AlarmManager
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class AlarmManager(Stub):
|
|
"""AlarmManager — 闹钟管理器"""
|
|
|
|
RTC_WAKEUP = 0
|
|
RTC = 1
|
|
ELAPSED_REALTIME_WAKEUP = 2
|
|
ELAPSED_REALTIME = 3
|
|
INTERVAL_FIFTEEN_MINUTES = 900000
|
|
INTERVAL_HALF_HOUR = 1800000
|
|
INTERVAL_HOUR = 3600000
|
|
INTERVAL_DAY = 86400000
|
|
FLAG_ALLOW_WHILE_IDLE_UNSCREEN_ON = 0x00000008
|
|
FLAG_ALLOW_WHILE_IDLE = 0x00000004
|
|
FLAG_STANDALONE = 0x00000002
|
|
FLAG_WAKE_FROM_IDLE = 0x00000001
|
|
|
|
def __init__(self, context: Any = None):
|
|
super().__init__()
|
|
self._context = context
|
|
self._alarms: List[Dict[str, Any]] = []
|
|
self._lock = threading.Lock()
|
|
self._next_id = 1
|
|
self._worker: Optional[threading.Thread] = None
|
|
self._running = True
|
|
|
|
def set(self, type_: int, triggerAtMillis: int, operation: Any) -> None:
|
|
with self._lock:
|
|
self._alarms.append({
|
|
"id": self._next_id,
|
|
"type": type_,
|
|
"trigger": triggerAtMillis,
|
|
"operation": operation,
|
|
"interval": 0,
|
|
"repeat": False,
|
|
"window": 0,
|
|
"allow_while_idle": False,
|
|
})
|
|
self._next_id += 1
|
|
|
|
def setRepeating(self, type_: int, triggerAtMillis: int, intervalMillis: int, operation: Any) -> None:
|
|
with self._lock:
|
|
self._alarms.append({
|
|
"id": self._next_id,
|
|
"type": type_,
|
|
"trigger": triggerAtMillis,
|
|
"operation": operation,
|
|
"interval": intervalMillis,
|
|
"repeat": True,
|
|
"window": 0,
|
|
"allow_while_idle": False,
|
|
})
|
|
self._next_id += 1
|
|
|
|
def setWindow(self, type_: int, windowStartMillis: int, windowLengthMillis: int, operation: Any) -> None:
|
|
with self._lock:
|
|
self._alarms.append({
|
|
"id": self._next_id,
|
|
"type": type_,
|
|
"trigger": windowStartMillis,
|
|
"operation": operation,
|
|
"interval": 0,
|
|
"repeat": False,
|
|
"window": windowLengthMillis,
|
|
"allow_while_idle": False,
|
|
})
|
|
self._next_id += 1
|
|
|
|
def setExact(self, type_: int, triggerAtMillis: int, operation: Any) -> None:
|
|
self.set(type_, triggerAtMillis, operation)
|
|
|
|
def setExactAndAllowWhileIdle(self, type_: int, triggerAtMillis: int, operation: Any) -> None:
|
|
self.set(type_, triggerAtMillis, operation)
|
|
|
|
def setAlarmClock(self, info: Any, triggerAtMillis: int, operation: Any) -> None:
|
|
pass
|
|
|
|
def cancel(self, operation: Any) -> None:
|
|
with self._lock:
|
|
self._alarms = [a for a in self._alarms if a.get("operation") != operation]
|
|
|
|
def getNextAlarmClock(self) -> Optional[Any]:
|
|
return None
|
|
|
|
def canScheduleExactAlarms(self) -> bool:
|
|
return True
|
|
|
|
def toString(self) -> str:
|
|
return f"AlarmManager(alarms={len(self._alarms)})"
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# AppOpsManager
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class AppOpsManager(Stub):
|
|
"""AppOpsManager — 应用操作管理器"""
|
|
|
|
MODE_ALLOWED = 0
|
|
MODE_IGNORED = 1
|
|
MODE_ERRORED = 2
|
|
MODE_DEFAULT = 3
|
|
MODE_FOREGROUND = 4
|
|
|
|
OPSTR_COARSE_LOCATION = "android:coarse_location"
|
|
OPSTR_FINE_LOCATION = "android:fine_location"
|
|
OPSTR_CAMERA = "android:camera"
|
|
OPSTR_RECORD_AUDIO = "android:record_audio"
|
|
OPSTR_READ_CONTACTS = "android:read_contacts"
|
|
OPSTR_WRITE_CONTACTS = "android:write_contacts"
|
|
OPSTR_READ_EXTERNAL_STORAGE = "android:read_external_storage"
|
|
OPSTR_WRITE_EXTERNAL_STORAGE = "android:write_external_storage"
|
|
OPSTR_ACCESS_NOTIFICATIONS = "android:access_notifications"
|
|
OPSTR_POST_NOTIFICATIONS = "android:post_notifications"
|
|
OPSTR_VIBRATE = "android:vibrate"
|
|
OPSTR_CALL_PHONE = "android:call_phone"
|
|
OPSTR_READ_SMS = "android:read_sms"
|
|
OPSTR_SEND_SMS = "android:send_sms"
|
|
OPSTR_RECEIVE_SMS = "android:receive_sms"
|
|
OPSTR_SYSTEM_ALERT_WINDOW = "android:system_alert_window"
|
|
OPSTR_REQUEST_INSTALL_PACKAGES = "android:request_install_packages"
|
|
OPSTR_BLUETOOTH = "android:bluetooth"
|
|
OPSTR_BLUETOOTH_SCAN = "android:bluetooth_scan"
|
|
OPSTR_BLUETOOTH_ADVERTISE = "android:bluetooth_advertise"
|
|
OPSTR_BLUETOOTH_CONNECT = "android:bluetooth_connect"
|
|
OPSTR_NFC = "android:nfc"
|
|
OPSTR_NFC_PREFERRED_PAYMENT = "android:nfc_preferred_payment"
|
|
OPSTR_PICTURE_IN_PICTURE = "android:picture_in_picture"
|
|
OPSTR_FOREGROUND_SERVICE = "android:foreground_service"
|
|
OPSTR_MANAGE_EXTERNAL_STORAGE = "android:manage_external_storage"
|
|
OPSTR_BODY_SENSORS = "android:body_sensors"
|
|
OPSTR_ACTIVITY_RECOGNITION = "android:activity_recognition"
|
|
OPSTR_USE_BIOMETRIC = "android:use_biometric"
|
|
OPSTR_USE_FINGERPRINT = "android:use_fingerprint"
|
|
|
|
def __init__(self, context: Any = None):
|
|
super().__init__()
|
|
self._context = context
|
|
self._op_modes: Dict[str, Dict[str, int]] = {}
|
|
self._lock = threading.Lock()
|
|
|
|
def checkOp(self, op: str, uid: int, packageName: str) -> int:
|
|
with self._lock:
|
|
if packageName not in self._op_modes:
|
|
return AppOpsManager.MODE_ALLOWED
|
|
return self._op_modes[packageName].get(op, AppOpsManager.MODE_ALLOWED)
|
|
|
|
def noteOp(self, op: str, uid: int, packageName: str) -> int:
|
|
return self.checkOp(op, uid, packageName)
|
|
|
|
def startOp(self, op: str, uid: int, packageName: str) -> int:
|
|
return self.checkOp(op, uid, packageName)
|
|
|
|
def finishOp(self, op: str, uid: int, packageName: str) -> None:
|
|
pass
|
|
|
|
def setMode(self, code: int, uid: int, packageName: str, mode: int) -> None:
|
|
with self._lock:
|
|
if packageName not in self._op_modes:
|
|
self._op_modes[packageName] = {}
|
|
self._op_modes[packageName][str(code)] = mode
|
|
|
|
def toString(self) -> str:
|
|
return f"AppOpsManager(packages={len(self._op_modes)})"
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# ClipboardManager
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class ClipboardManager(Stub):
|
|
"""ClipboardManager — 剪贴板管理器"""
|
|
|
|
def __init__(self, context: Any = None):
|
|
super().__init__()
|
|
self._context = context
|
|
self._primary_clip: Optional[Any] = None
|
|
self._listeners: List[Callable] = []
|
|
self._has_clipboard = True
|
|
self._clipboard_history: List[Any] = []
|
|
self._max_history = 10
|
|
|
|
def setPrimaryClip(self, clip: Any) -> None:
|
|
self._primary_clip = clip
|
|
if clip is not None:
|
|
self._clipboard_history.append(clip)
|
|
if len(self._clipboard_history) > self._max_history:
|
|
self._clipboard_history.pop(0)
|
|
for listener in self._listeners:
|
|
try:
|
|
listener(clip)
|
|
except Exception:
|
|
pass
|
|
|
|
def clearPrimaryClip(self) -> None:
|
|
if self._primary_clip is not None:
|
|
self._clipboard_history.append(None)
|
|
self._primary_clip = None
|
|
|
|
def getPrimaryClip(self) -> Optional[Any]:
|
|
return self._primary_clip
|
|
|
|
def hasPrimaryClip(self) -> bool:
|
|
return self._primary_clip is not None
|
|
|
|
def hasClipboardText(self) -> bool:
|
|
if self._primary_clip is None:
|
|
return False
|
|
try:
|
|
return hasattr(self._primary_clip, "getText") and self._primary_clip.getText() is not None
|
|
except Exception:
|
|
return False
|
|
|
|
def getText(self) -> Optional[str]:
|
|
if self._primary_clip is not None:
|
|
try:
|
|
return self._primary_clip.getText()
|
|
except Exception:
|
|
pass
|
|
return None
|
|
|
|
def addPrimaryClipChangedListener(self, listener: Callable) -> None:
|
|
if listener not in self._listeners:
|
|
self._listeners.append(listener)
|
|
|
|
def removePrimaryClipChangedListener(self, listener: Callable) -> None:
|
|
if listener in self._listeners:
|
|
self._listeners.remove(listener)
|
|
|
|
def getClipboardHistory(self) -> List[Any]:
|
|
return list(self._clipboard_history)
|
|
|
|
def toString(self) -> str:
|
|
return f"ClipboardManager(has_clip={self.hasPrimaryClip()})"
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# ConnectivityManager (扩展)
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class ConnectivityManager(Stub):
|
|
"""ConnectivityManager — 连接管理器 (扩展)"""
|
|
|
|
TYPE_NONE = -1
|
|
TYPE_MOBILE = 0
|
|
TYPE_WIFI = 1
|
|
TYPE_MOBILE_MMS = 2
|
|
TYPE_MOBILE_SUPL = 3
|
|
TYPE_MOBILE_DUN = 4
|
|
TYPE_MOBILE_HIPRI = 5
|
|
TYPE_WIMAX = 6
|
|
TYPE_BLUETOOTH = 7
|
|
TYPE_DUMMY = 8
|
|
TYPE_ETHERNET = 9
|
|
TYPE_VPN = 17
|
|
TYPE_WIFI_P2P = 13
|
|
|
|
EXTRA_NETWORK_TYPE = "networkType"
|
|
EXTRA_IS_FAILOVER = "isFailover"
|
|
EXTRA_OTHER_NETWORK_INFO = "otherNetwork"
|
|
EXTRA_NO_CONNECTIVITY = "noConnectivity"
|
|
EXTRA_REASON = "reason"
|
|
EXTRA_EXTRA_INFO = "extraInfo"
|
|
EXTRA_NETWORK_INFO = "networkInfo"
|
|
EXTRA_NETWORK_REQUEST = "networkRequest"
|
|
EXTRA_NETWORK = "network"
|
|
|
|
CONNECTIVITY_ACTION = "android.net.conn.CONNECTIVITY_CHANGE"
|
|
|
|
def __init__(self, context: Any = None):
|
|
super().__init__()
|
|
self._context = context
|
|
self._active_network_info: Optional[Any] = None
|
|
self._network_preference = ConnectivityManager.TYPE_WIFI
|
|
self._background_data_setting = True
|
|
self._network_callbacks: List[Any] = []
|
|
self._active_network: Optional[Any] = None
|
|
self._all_networks: List[Any] = []
|
|
|
|
def _get_linux_active_info(self):
|
|
"""从 Linux 真实网络信息构造活跃 NetworkInfo"""
|
|
try:
|
|
from .net import NetworkInfo
|
|
interfaces = LinuxNetwork.get_interfaces()
|
|
# 有真实网络接口 (非环回) 且 operstate=up 即视为已连接
|
|
connected = any(
|
|
(iface.get("ifname") or iface.get("name", "")) != "lo"
|
|
and iface.get("operstate", "").lower() == "up"
|
|
for iface in interfaces
|
|
)
|
|
if not connected:
|
|
connected = LinuxNetwork.get_connectivity()
|
|
ip = LinuxNetwork.get_ip_address()
|
|
iface_name = ""
|
|
net_type = ConnectivityManager.TYPE_ETHERNET
|
|
for iface in interfaces:
|
|
name = iface.get("ifname") or iface.get("name", "")
|
|
state = iface.get("operstate", "")
|
|
if name and name != "lo" and state.lower() == "up":
|
|
iface_name = iface_name or name
|
|
if name and name.startswith(("wl", "wlan", "wlp")):
|
|
net_type = ConnectivityManager.TYPE_WIFI
|
|
iface_name = name
|
|
data = {
|
|
"connected": connected,
|
|
"ip": ip,
|
|
"interface": iface_name,
|
|
"type_name": "WIFI" if net_type == ConnectivityManager.TYPE_WIFI else "ETHERNET",
|
|
}
|
|
return NetworkInfo.from_linux_data(data, network_type=net_type)
|
|
except Exception:
|
|
return self._active_network_info
|
|
|
|
def getActiveNetworkInfo(self) -> Optional[Any]:
|
|
if _USE_LINUX:
|
|
return self._get_linux_active_info()
|
|
return self._active_network_info
|
|
|
|
def getNetworkInfo(self, networkType: int) -> Optional[Any]:
|
|
if _USE_LINUX:
|
|
info = self._get_linux_active_info()
|
|
if info is not None and info.getType() == networkType:
|
|
return info
|
|
return None
|
|
return None
|
|
|
|
def getConnectivityStatus(self) -> bool:
|
|
"""返回当前网络连通性 (True=已连接)"""
|
|
if _USE_LINUX:
|
|
return LinuxNetwork.get_connectivity()
|
|
return False
|
|
|
|
def getAllNetworkInfo(self) -> List[Any]:
|
|
return self._all_networks
|
|
|
|
def isActiveNetworkMetered(self) -> bool:
|
|
return True
|
|
|
|
def getActiveNetwork(self) -> Optional[Any]:
|
|
return self._active_network
|
|
|
|
def getAllNetworks(self) -> List[Any]:
|
|
return list(self._all_networks)
|
|
|
|
def requestNetwork(self, request: Any, callback: Any) -> None:
|
|
pass
|
|
|
|
def registerNetworkCallback(self, request: Any, callback: Any) -> None:
|
|
if callback not in self._network_callbacks:
|
|
self._network_callbacks.append(callback)
|
|
|
|
def unregisterNetworkCallback(self, callback: Any) -> None:
|
|
if callback in self._network_callbacks:
|
|
self._network_callbacks.remove(callback)
|
|
|
|
def getNetworkCapabilities(self, network: Any) -> Optional[Any]:
|
|
return None
|
|
|
|
def getLinkProperties(self, network: Any) -> Optional[Any]:
|
|
return None
|
|
|
|
def setNetworkPreference(self, preference: int) -> None:
|
|
self._network_preference = preference
|
|
|
|
def getBackgroundDataSetting(self) -> bool:
|
|
return self._background_data_setting
|
|
|
|
def setBackgroundDataSetting(self, allow: bool) -> None:
|
|
self._background_data_setting = allow
|
|
|
|
def reportBadNetwork(self, network: Any) -> None:
|
|
pass
|
|
|
|
def toString(self) -> str:
|
|
return f"ConnectivityManager(active={self._active_network_info is not None})"
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# DevicePolicyManager (扩展)
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class DevicePolicyManager(Stub):
|
|
"""DevicePolicyManager — 设备策略管理器 (扩展)"""
|
|
|
|
ACTION_ADD_DEVICE_ADMIN = "android.app.action.ADD_DEVICE_ADMIN"
|
|
ACTION_DEVICE_ADMIN_ENABLED = "android.app.action.DEVICE_ADMIN_ENABLED"
|
|
ACTION_DEVICE_ADMIN_DISABLED = "android.app.action.DEVICE_ADMIN_DISABLED"
|
|
ACTION_SET_NEW_PASSWORD = "android.app.action.SET_NEW_PASSWORD"
|
|
ACTION_START_ENCRYPTION = "android.app.action.START_ENCRYPTION"
|
|
ACTION_PROVISION_MANAGED_PROFILE = "android.app.action.PROVISION_MANAGED_PROFILE"
|
|
ACTION_SYSTEM_UPDATE_POLICY = "android.app.action.SYSTEM_UPDATE_POLICY"
|
|
|
|
KEYGUARD_DISABLE_FEATURES_NONE = 0
|
|
KEYGUARD_DISABLE_FEATURES_ALL = 0x7FFFFFFF
|
|
KEYGUARD_DISABLE_SECURE_CAMERA = 2
|
|
KEYGUARD_DISABLE_FINGERPRINT = 32
|
|
KEYGUARD_DISABLE_REMOTE_INPUT = 64
|
|
KEYGUARD_DISABLE_FACE = 128
|
|
KEYGUARD_DISABLE_IRIS = 256
|
|
KEYGUARD_DISABLE_BIOMETRICS = 32 | 128 | 256
|
|
KEYGUARD_DISABLE_SHORTCUTS = 512
|
|
KEYGUARD_DISABLE_WIDGETS_ALL = 1048576
|
|
|
|
PASSWORD_QUALITY_UNSPECIFIED = 0
|
|
PASSWORD_QUALITY_SOMETHING = 0x10000
|
|
PASSWORD_QUALITY_NUMERIC = 0x20000
|
|
PASSWORD_QUALITY_NUMERIC_COMPLEX = 0x30000
|
|
PASSWORD_QUALITY_ALPHABETIC = 0x40000
|
|
PASSWORD_QUALITY_ALPHANUMERIC = 0x50000
|
|
PASSWORD_QUALITY_COMPLEX = 0x60000
|
|
PASSWORD_QUALITY_MANAGED = 0x80000
|
|
PASSWORD_QUALITY_BIOMETRIC_WEAK = 0x8000
|
|
|
|
RESET_PASSWORD_REQUIRE_ENTRY = 0x0001
|
|
RESET_PASSWORD_DO_NOT_ASK_CREDENTIALS_ON_BOOT = 0x0002
|
|
|
|
def __init__(self, context: Any = None):
|
|
super().__init__()
|
|
self._context = context
|
|
self._admin_receivers: List[Any] = []
|
|
self._password_quality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED
|
|
self._password_length = 0
|
|
self._maximum_failed_passwords_for_wipe = 0
|
|
self._maximum_time_to_lock = 0
|
|
self._storage_encryption = False
|
|
self._camera_disabled = False
|
|
self._screen_capture_disabled = False
|
|
self._keyguard_disabled_features = DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_NONE
|
|
self._lock_task_packages: List[str] = []
|
|
|
|
def isDeviceOwnerApp(self, packageName: str) -> bool:
|
|
return False
|
|
|
|
def isProfileOwnerApp(self, packageName: str) -> bool:
|
|
return False
|
|
|
|
def getDeviceOwner(self) -> Optional[str]:
|
|
return None
|
|
|
|
def getProfileOwner(self) -> Optional[Any]:
|
|
return None
|
|
|
|
def setPasswordQuality(self, admin: Any, quality: int) -> None:
|
|
self._password_quality = quality
|
|
|
|
def getPasswordQuality(self, admin: Any = None) -> int:
|
|
return self._password_quality
|
|
|
|
def setPasswordMinimumLength(self, admin: Any, length: int) -> None:
|
|
self._password_length = length
|
|
|
|
def getPasswordMinimumLength(self, admin: Any = None) -> int:
|
|
return self._password_length
|
|
|
|
def resetPassword(self, password: str, flags: int = 0) -> bool:
|
|
return True
|
|
|
|
def setMaximumFailedPasswordsForWipe(self, admin: Any, num: int) -> None:
|
|
self._maximum_failed_passwords_for_wipe = num
|
|
|
|
def getMaximumFailedPasswordsForWipe(self, admin: Any = None) -> int:
|
|
return self._maximum_failed_passwords_for_wipe
|
|
|
|
def setMaximumTimeToLock(self, admin: Any, timeMs: int) -> None:
|
|
self._maximum_time_to_lock = timeMs
|
|
|
|
def getMaximumTimeToLock(self, admin: Any = None) -> int:
|
|
return self._maximum_time_to_lock
|
|
|
|
def lockNow(self) -> None:
|
|
pass
|
|
|
|
def wipeData(self, flags: int = 0) -> None:
|
|
raise RuntimeError("wipeData() would wipe device data")
|
|
|
|
def setStorageEncryption(self, admin: Any, encrypt: bool) -> int:
|
|
self._storage_encryption = encrypt
|
|
return 1
|
|
|
|
def getStorageEncryption(self, admin: Any = None) -> bool:
|
|
return self._storage_encryption
|
|
|
|
def setCameraDisabled(self, admin: Any, disabled: bool) -> None:
|
|
self._camera_disabled = disabled
|
|
|
|
def getCameraDisabled(self, admin: Any = None) -> bool:
|
|
return self._camera_disabled
|
|
|
|
def setScreenCaptureDisabled(self, admin: Any, disabled: bool) -> None:
|
|
self._screen_capture_disabled = disabled
|
|
|
|
def getScreenCaptureDisabled(self, admin: Any = None) -> bool:
|
|
return self._screen_capture_disabled
|
|
|
|
def setKeyguardDisabledFeatures(self, admin: Any, features: int) -> None:
|
|
self._keyguard_disabled_features = features
|
|
|
|
def getKeyguardDisabledFeatures(self, admin: Any = None) -> int:
|
|
return self._keyguard_disabled_features
|
|
|
|
def setLockTaskPackages(self, admin: Any, packages: List[str]) -> None:
|
|
self._lock_task_packages = list(packages)
|
|
|
|
def getLockTaskPackages(self, admin: Any = None) -> List[str]:
|
|
return list(self._lock_task_packages)
|
|
|
|
def isLockTaskPermitted(self, pkg: str) -> bool:
|
|
return pkg in self._lock_task_packages
|
|
|
|
def toString(self) -> str:
|
|
return f"DevicePolicyManager(password_quality=0x{self._password_quality:x})"
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# DisplayManager (扩展)
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class DisplayManager(Stub):
|
|
"""DisplayManager — 显示管理器 (扩展)"""
|
|
|
|
DISPLAY_CATEGORY_PRESENTATION = "android.hardware.display.category.PRESENTATION"
|
|
VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR = 0x00000001
|
|
VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY = 0x00000002
|
|
VIRTUAL_DISPLAY_FLAG_PRESENTATION = 0x00000004
|
|
VIRTUAL_DISPLAY_FLAG_SECURE = 0x00000008
|
|
VIRTUAL_DISPLAY_FLAG_PUBLIC = 0x00000010
|
|
VIRTUAL_DISPLAY_FLAG_SUPPORTS_TOUCH = 0x00000020
|
|
VIRTUAL_DISPLAY_FLAG_ROTATES_WITH_CONTENT = 0x00000040
|
|
VIRTUAL_DISPLAY_FLAG_DESTROY_CONTENT_ON_SURFACE = 0x00000080
|
|
|
|
def __init__(self, context: Any = None):
|
|
super().__init__()
|
|
self._context = context
|
|
self._displays: Dict[int, Any] = {}
|
|
self._display_listeners: List[Any] = []
|
|
self._default_display: Optional[Any] = None
|
|
self._virtual_displays: Dict[str, Any] = {}
|
|
|
|
def getDisplay(self, displayId: int) -> Optional[Any]:
|
|
return self._displays.get(displayId)
|
|
|
|
def getDisplays(self, category: Optional[str] = None) -> List[Any]:
|
|
if category:
|
|
return [d for d in self._displays.values()]
|
|
return list(self._displays.values())
|
|
|
|
def getDefaultDisplay(self) -> Optional[Any]:
|
|
return self._default_display
|
|
|
|
def registerDisplayListener(self, listener: Any, handler: Any = None) -> None:
|
|
if listener not in self._display_listeners:
|
|
self._display_listeners.append(listener)
|
|
|
|
def unregisterDisplayListener(self, listener: Any) -> None:
|
|
if listener in self._display_listeners:
|
|
self._display_listeners.remove(listener)
|
|
|
|
def createVirtualDisplay(
|
|
self, name: str, width: int, height: int, densityDpi: int,
|
|
surface: Any, flags: int = 0
|
|
) -> Optional[Any]:
|
|
return None
|
|
|
|
def toString(self) -> str:
|
|
return f"DisplayManager(displays={len(self._displays)})"
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# DownloadManager
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class DownloadManager(Stub):
|
|
"""DownloadManager — 下载管理器"""
|
|
|
|
ACTION_DOWNLOAD_COMPLETE = "android.intent.action.DOWNLOAD_COMPLETE"
|
|
ACTION_NOTIFICATION_CLICKED = "android.intent.action.DOWNLOAD_NOTIFICATION_CLICKED"
|
|
ACTION_VIEW_DOWNLOADS = "android.intent.action.VIEW_DOWNLOADS"
|
|
EXTRA_DOWNLOAD_ID = "extraDownloadId"
|
|
EXTRA_NOTIFICATION_CLICK_DOWNLOAD_IDS = "extraNotificationClickDownloadIds"
|
|
INTENT_EXTRAS_SORT_BY_SIZE = "android.app.DownloadManager.extraSortBySize"
|
|
|
|
COLUMN_ID = "_id"
|
|
COLUMN_TITLE = "title"
|
|
COLUMN_DESCRIPTION = "description"
|
|
COLUMN_URI = "uri"
|
|
COLUMN_STATUS = "status"
|
|
COLUMN_REASON = "reason"
|
|
COLUMN_TOTAL_SIZE_BYTES = "total_size"
|
|
COLUMN_BYTES_DOWNLOADED_SO_FAR = "bytes_so_far"
|
|
COLUMN_MEDIA_TYPE = "media_type"
|
|
COLUMN_LOCAL_FILENAME = "local_filename"
|
|
COLUMN_LOCAL_URI = "local_uri"
|
|
COLUMN_LAST_MODIFIED_TIMESTAMP = "last_modified_timestamp"
|
|
|
|
STATUS_PENDING = 1
|
|
STATUS_RUNNING = 2
|
|
STATUS_PAUSED = 3
|
|
STATUS_SUCCESSFUL = 4
|
|
STATUS_FAILED = 5
|
|
STATUS_QUEUED = 6
|
|
STATUS_WAITING = 7
|
|
STATUS_WAITING_FOR_NETWORK = 8
|
|
STATUS_WAITING_FOR_WIFI = 9
|
|
|
|
ERROR_UNKNOWN = 1000
|
|
ERROR_DEVICE_NOT_FOUND = 1001
|
|
ERROR_CANNOT_RESUME = 1002
|
|
ERROR_FILE_ALREADY_EXISTS = 1003
|
|
ERROR_FILE_ERROR = 1004
|
|
ERROR_HTTP_DATA_ERROR = 1005
|
|
ERROR_INSUFFICIENT_SPACE = 1006
|
|
ERROR_TOO_MANY_REDIRECTS = 1007
|
|
ERROR_UNHANDLED_HTTP_CODE = 1008
|
|
ERROR_HTTP_406 = 1009
|
|
|
|
PAUSED_QUEUED_FOR_WIFI = 1
|
|
PAUSED_WAITING_TO_RETRY = 2
|
|
PAUSED_WAITING_FOR_NETWORK = 3
|
|
PAUSED_UNKNOWN = 4
|
|
|
|
def __init__(self, context: Any = None):
|
|
super().__init__()
|
|
self._context = context
|
|
self._downloads: Dict[int, Dict[str, Any]] = {}
|
|
self._next_id = 1
|
|
self._lock = threading.Lock()
|
|
|
|
def enqueue(self, request: Any) -> int:
|
|
with self._lock:
|
|
download_id = self._next_id
|
|
self._next_id += 1
|
|
self._downloads[download_id] = {
|
|
"id": download_id,
|
|
"status": DownloadManager.STATUS_PENDING,
|
|
"reason": 0,
|
|
"title": "",
|
|
"description": "",
|
|
"uri": "",
|
|
"total_size": -1,
|
|
"bytes_so_far": 0,
|
|
"local_filename": "",
|
|
}
|
|
return download_id
|
|
|
|
def query(self, query: Any) -> Any:
|
|
return None
|
|
|
|
def remove(self, varargs: List[int]) -> int:
|
|
removed = 0
|
|
with self._lock:
|
|
for download_id in varargs:
|
|
if download_id in self._downloads:
|
|
del self._downloads[download_id]
|
|
removed += 1
|
|
return removed
|
|
|
|
def getUriForDownloadedFile(self, downloadId: int) -> Optional[str]:
|
|
return None
|
|
|
|
def getMimeTypeForDownloadedFile(self, downloadId: int) -> Optional[str]:
|
|
return None
|
|
|
|
def restartDownload(self, downloadId: int) -> bool:
|
|
return False
|
|
|
|
def toString(self) -> str:
|
|
return f"DownloadManager(downloads={len(self._downloads)})"
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# DropBoxManager
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class DropBoxManager(Stub):
|
|
"""DropBoxManager — 日志收集管理器"""
|
|
|
|
IS_EMPTY = 0
|
|
IS_TEXT = 1
|
|
IS_GZIPPED = 2
|
|
IS_ENCRYPTED = 4
|
|
|
|
def __init__(self, context: Any = None):
|
|
super().__init__()
|
|
self._entries: Dict[str, List[Any]] = {}
|
|
self._max_entries = 100
|
|
|
|
def addText(self, tag: str, data: str) -> None:
|
|
if tag not in self._entries:
|
|
self._entries[tag] = []
|
|
self._entries[tag].append(("text", data, time.time()))
|
|
if len(self._entries[tag]) > self._max_entries:
|
|
self._entries[tag].pop(0)
|
|
|
|
def addData(self, tag: str, data: bytes, flags: int = 0) -> None:
|
|
if tag not in self._entries:
|
|
self._entries[tag] = []
|
|
self._entries[tag].append(("data", data, time.time(), flags))
|
|
if len(self._entries[tag]) > self._max_entries:
|
|
self._entries[tag].pop(0)
|
|
|
|
def getNextEntry(self, tag: str, msec: int) -> Optional[Any]:
|
|
return None
|
|
|
|
def isTagEnabled(self, tag: str) -> bool:
|
|
return True
|
|
|
|
def dump(self, pw: Any) -> None:
|
|
pass
|
|
|
|
def toString(self) -> str:
|
|
return f"DropBoxManager(entries={sum(len(v) for v in self._entries.values())})"
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# FocusManager
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class FocusManager(Stub):
|
|
"""FocusManager — 焦点管理器"""
|
|
|
|
def __init__(self, context: Any = None):
|
|
super().__init__()
|
|
self._context = context
|
|
self._focused_view: Optional[Any] = None
|
|
self._focus_cycle_enabled = True
|
|
self._focus_search_enabled = True
|
|
|
|
def getFocusedView(self) -> Optional[Any]:
|
|
return self._focused_view
|
|
|
|
def setFocusedView(self, view: Any) -> None:
|
|
self._focused_view = view
|
|
|
|
def clearFocus(self) -> None:
|
|
self._focused_view = None
|
|
|
|
def isFocusCycleEnabled(self) -> bool:
|
|
return self._focus_cycle_enabled
|
|
|
|
def setFocusCycleEnabled(self, enabled: bool) -> None:
|
|
self._focus_cycle_enabled = enabled
|
|
|
|
def requestFocus(self, view: Any, direction: int = 0) -> bool:
|
|
self._focused_view = view
|
|
return True
|
|
|
|
def toString(self) -> str:
|
|
return f"FocusManager(focused={self._focused_view is not None})"
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# LauncherApps
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class LauncherApps(Stub):
|
|
"""LauncherApps — 启动器应用管理器"""
|
|
|
|
def __init__(self, context: Any = None):
|
|
super().__init__()
|
|
self._context = context
|
|
self._callbacks: List[Any] = []
|
|
self._shortcuts: Dict[str, List[Any]] = {}
|
|
|
|
def getActivityList(self, packageName: str, user: Any) -> List[Any]:
|
|
return []
|
|
|
|
def getApplicationList(self, user: Any) -> List[Any]:
|
|
return []
|
|
|
|
def startAppDetails(self, component: Any, user: Any, sourceBounds: Any, opts: Any) -> None:
|
|
pass
|
|
|
|
def startMainActivity(self, component: Any, user: Any, sourceBounds: Any, opts: Any) -> None:
|
|
pass
|
|
|
|
def getShortcutConfigActivityList(self, packageName: str, user: Any) -> List[Any]:
|
|
return []
|
|
|
|
def hasShortcutHostPermission(self) -> bool:
|
|
return True
|
|
|
|
def getShortcuts(self, filter_: Any, user: Any) -> List[Any]:
|
|
return []
|
|
|
|
def pinShortcuts(self, packageName: str, shortcutIds: List[str], user: Any) -> bool:
|
|
return True
|
|
|
|
def registerCallback(self, callback: Any) -> None:
|
|
if callback not in self._callbacks:
|
|
self._callbacks.append(callback)
|
|
|
|
def unregisterCallback(self, callback: Any) -> None:
|
|
if callback in self._callbacks:
|
|
self._callbacks.remove(callback)
|
|
|
|
def toString(self) -> str:
|
|
return f"LauncherApps(callbacks={len(self._callbacks)})"
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# MediaRouter
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class MediaRouter(Stub):
|
|
"""MediaRouter — 媒体路由管理器"""
|
|
|
|
ROUTE_TYPE_LIVE_AUDIO = 1
|
|
ROUTE_TYPE_LIVE_VIDEO = 2
|
|
ROUTE_TYPE_REMOTE_DISPLAY = 4
|
|
ROUTE_TYPE_USER = 8
|
|
ROUTE_TYPE_ANY = 0x800000
|
|
|
|
UNSELECT_REASON_UNKNOWN = 0
|
|
UNSELECT_REASON_ROUTE_CHANGED = 1
|
|
UNSELECT_REASON_DISCONNECTED = 2
|
|
UNSELECT_REASON_STOPPED = 3
|
|
|
|
def __init__(self, context: Any = None):
|
|
super().__init__()
|
|
self._context = context
|
|
self._routes: List[Any] = []
|
|
self._selected_route: Optional[Any] = None
|
|
self._default_route: Optional[Any] = None
|
|
self._callbacks: List[Any] = []
|
|
|
|
def getDefaultRoute(self) -> Optional[Any]:
|
|
return self._default_route
|
|
|
|
def getSelectedRoute(self, type_: int) -> Optional[Any]:
|
|
return self._selected_route
|
|
|
|
def selectRoute(self, type_: int, route: Any) -> None:
|
|
self._selected_route = route
|
|
|
|
def addCallback(self, types: int, cb: Any) -> None:
|
|
if cb not in self._callbacks:
|
|
self._callbacks.append(cb)
|
|
|
|
def removeCallback(self, cb: Any) -> None:
|
|
if cb in self._callbacks:
|
|
self._callbacks.remove(cb)
|
|
|
|
def getRoutes(self) -> List[Any]:
|
|
return list(self._routes)
|
|
|
|
def isUserRouteAllowed(self) -> bool:
|
|
return True
|
|
|
|
def toString(self) -> str:
|
|
return f"MediaRouter(routes={len(self._routes)})"
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# NetworkPolicyManager
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class NetworkPolicyManager(Stub):
|
|
"""NetworkPolicyManager — 网络策略管理器"""
|
|
|
|
POLICY_NONE = 0
|
|
POLICY_REJECT_METERED_BACKGROUND = 1
|
|
POLICY_ALLOW_METERED_BACKGROUND = 4
|
|
|
|
RULE_ALLOW_ALL = 0
|
|
RULE_REJECT_METERED = 1
|
|
RULE_REJECT_ALL = 2
|
|
RULE_TEMPORARY_ALLOW_METERED = 3
|
|
|
|
def __init__(self, context: Any = None):
|
|
super().__init__()
|
|
self._context = context
|
|
self._uid_policies: Dict[int, int] = {}
|
|
self._uid_rules: Dict[int, int] = {}
|
|
self._restrict_background = False
|
|
|
|
def getUidPolicy(self, uid: int) -> int:
|
|
return self._uid_policies.get(uid, NetworkPolicyManager.POLICY_NONE)
|
|
|
|
def setUidPolicy(self, uid: int, policy: int) -> None:
|
|
self._uid_policies[uid] = policy
|
|
|
|
def getUidsWithPolicy(self, policy: int) -> List[int]:
|
|
return [uid for uid, p in self._uid_policies.items() if p == policy]
|
|
|
|
def isUidNetworkingBlocked(self, uid: int, metered: bool) -> bool:
|
|
return False
|
|
|
|
def registerListener(self, listener: Any) -> None:
|
|
pass
|
|
|
|
def unregisterListener(self, listener: Any) -> None:
|
|
pass
|
|
|
|
def toString(self) -> str:
|
|
return f"NetworkPolicyManager(uids={len(self._uid_policies)})"
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# NotificationManager (扩展)
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class NotificationManagerExt(Stub):
|
|
"""NotificationManager (Extension) — 额外通知管理器功能"""
|
|
|
|
def __init__(self, context: Any = None):
|
|
super().__init__()
|
|
self._context = context
|
|
|
|
def getSnoozeIntentForChannel(self, channelId: str) -> Optional[Any]:
|
|
return None
|
|
|
|
def matchesCallFilter(self, address: Any) -> bool:
|
|
return True
|
|
|
|
def getActiveNotificationsFromBinder(self) -> List[Any]:
|
|
return []
|
|
|
|
def getHistoricalNotifications(self) -> List[Any]:
|
|
return []
|
|
|
|
def canNotifyAsPackage(self, pkg: str) -> bool:
|
|
return True
|
|
|
|
def setNotificationDelegate(self, delegate: str) -> None:
|
|
pass
|
|
|
|
def getNotificationDelegate(self) -> Optional[str]:
|
|
return None
|
|
|
|
def updateNotificationChannelGroup(self, group: Any) -> None:
|
|
pass
|
|
|
|
def toString(self) -> str:
|
|
return "NotificationManager(Extension)"
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# NsdManager (quick reference for net_nsd 模块)
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class NsdManagerQuick(Stub):
|
|
"""NsdManager (Quick Reference)"""
|
|
|
|
PROTOCOL_DNS_SD = 0
|
|
FAILURE_ALREADY_ACTIVE = 3
|
|
FAILURE_INTERNAL_ERROR = 0
|
|
FAILURE_MAX_LIMIT = 4
|
|
FAILURE_SERVICE_NOT_FOUND = 1
|
|
FAILURE_SERVICE_NOT_RUNNING = 2
|
|
|
|
def __init__(self, context: Any = None):
|
|
super().__init__()
|
|
self._context = context
|
|
|
|
def discoverServices(self, serviceType: str, protocolType: int, listener: Any) -> None:
|
|
pass
|
|
|
|
def stopServiceDiscovery(self, listener: Any) -> None:
|
|
pass
|
|
|
|
def registerService(self, serviceInfo: Any, protocolType: int, listener: Any) -> None:
|
|
pass
|
|
|
|
def unregisterService(self, listener: Any) -> None:
|
|
pass
|
|
|
|
def resolveService(self, serviceInfo: Any, listener: Any) -> None:
|
|
pass
|
|
|
|
def toString(self) -> str:
|
|
return "NsdManager"
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# RestrictionManager
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class RestrictionManager(Stub):
|
|
"""RestrictionManager — 限制管理器"""
|
|
|
|
def __init__(self, context: Any = None):
|
|
super().__init__()
|
|
self._context = context
|
|
self._restrictions: Dict[str, Any] = {}
|
|
self._lock = threading.Lock()
|
|
|
|
def getApplicationRestrictions(self, packageName: str) -> Any:
|
|
return None
|
|
|
|
def setApplicationRestrictions(self, packageName: str, restrictions: Any) -> None:
|
|
pass
|
|
|
|
def hasRestrictionProvider(self) -> bool:
|
|
return False
|
|
|
|
def getManifestRestrictions(self, packageName: str) -> List[Any]:
|
|
return []
|
|
|
|
def getRestrictionsProvider(self, packageName: str) -> Optional[Any]:
|
|
return None
|
|
|
|
def notifyPermissionResponse(self, packageName: str, response: Any) -> None:
|
|
pass
|
|
|
|
def toString(self) -> str:
|
|
return "RestrictionManager"
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# SubscriptionManager
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class SubscriptionManager(Stub):
|
|
"""SubscriptionManager — 订阅管理器"""
|
|
|
|
DEFAULT_SUBSCRIPTION_ID = -1
|
|
INVALID_SUBSCRIPTION_ID = -2
|
|
ACTIVE_DATA_SUBSCRIPTION_ID = -3
|
|
|
|
EXTRA_SUBSCRIPTION_INDEX = "android.telephony.extra.SUBSCRIPTION_INDEX"
|
|
EXTRA_SLOT_INDEX = "android.telephony.extra.SLOT_INDEX"
|
|
|
|
def __init__(self, context: Any = None):
|
|
super().__init__()
|
|
self._context = context
|
|
self._subscriptions: List[Any] = []
|
|
|
|
def getActiveSubscriptionInfoList(self) -> List[Any]:
|
|
return list(self._subscriptions)
|
|
|
|
def getActiveSubscriptionInfo(self, subId: int) -> Optional[Any]:
|
|
for sub in self._subscriptions:
|
|
if getattr(sub, "subscriptionId", None) == subId:
|
|
return sub
|
|
return None
|
|
|
|
def getActiveSubscriptionInfoForSimSlotIndex(self, slotIndex: int) -> Optional[Any]:
|
|
for sub in self._subscriptions:
|
|
if getattr(sub, "simSlotIndex", None) == slotIndex:
|
|
return sub
|
|
return None
|
|
|
|
def getDefaultSubscriptionId(self) -> int:
|
|
return SubscriptionManager.DEFAULT_SUBSCRIPTION_ID
|
|
|
|
def setDefaultSubscriptionId(self, subId: int) -> None:
|
|
pass
|
|
|
|
def addOnSubscriptionsChangedListener(self, listener: Any) -> None:
|
|
pass
|
|
|
|
def removeOnSubscriptionsChangedListener(self, listener: Any) -> None:
|
|
pass
|
|
|
|
def getSlotIndex(self, subscriptionId: int) -> int:
|
|
return -1
|
|
|
|
def toString(self) -> str:
|
|
return f"SubscriptionManager(subscriptions={len(self._subscriptions)})"
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# WallpaperManager (扩展)
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class WallpaperManagerExt(Stub):
|
|
"""WallpaperManager (Extension)"""
|
|
|
|
def __init__(self, context: Any = None):
|
|
super().__init__()
|
|
self._context = context
|
|
|
|
def getWallpaperIdForWhom(self, which: int) -> int:
|
|
return -1
|
|
|
|
def getWallpaperUserId(self) -> int:
|
|
return 0
|
|
|
|
def setWallpaperOffsets(self, windowToken: Any, xOffset: float, yOffset: float) -> None:
|
|
pass
|
|
|
|
def clearWallpaperOffsets(self, windowToken: Any) -> None:
|
|
pass
|
|
|
|
def hasResourceWallpaper(self, resid: int) -> bool:
|
|
return False
|
|
|
|
def toString(self) -> str:
|
|
return "WallpaperManager(Extension)"
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# WifiP2pManager / WifiP2pDevice / WifiP2pGroup / WifiP2pConfig
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class WifiP2pDevice(Stub):
|
|
"""WifiP2pDevice — WiFi P2P 设备"""
|
|
|
|
CONNECTED = 0
|
|
INVITED = 1
|
|
FAILED = 2
|
|
AVAILABLE = 3
|
|
UNAVAILABLE = 4
|
|
|
|
def __init__(self):
|
|
super().__init__()
|
|
self.deviceName: Optional[str] = None
|
|
self.deviceAddress: Optional[str] = None
|
|
self.primaryDeviceType: Optional[str] = None
|
|
self.secondaryDeviceType: Optional[str] = None
|
|
self.status = WifiP2pDevice.AVAILABLE
|
|
self.wpsConfigMethodsSupported = 0
|
|
self.groupCapabilityFlags = 0
|
|
self.deviceCapabilityFlags = 0
|
|
self.serviceDiscoveryCapable = False
|
|
self.isGroupOwner = False
|
|
self._supports_wfd = False
|
|
self._interface_address: Optional[str] = None
|
|
|
|
def isGroupOwner(self) -> bool:
|
|
return self.isGroupOwner
|
|
|
|
def wpsDisplaySupported(self) -> bool:
|
|
return (self.wpsConfigMethodsSupported & 0x1000) != 0
|
|
|
|
def wpsKeypadSupported(self) -> bool:
|
|
return (self.wpsConfigMethodsSupported & 0x0100) != 0
|
|
|
|
def wpsPbcSupported(self) -> bool:
|
|
return (self.wpsConfigMethodsSupported & 0x0040) != 0
|
|
|
|
def equals(self, other: Any) -> bool:
|
|
if isinstance(other, WifiP2pDevice):
|
|
return self.deviceAddress == other.deviceAddress
|
|
return False
|
|
|
|
def hashCode(self) -> int:
|
|
return hash(self.deviceAddress) & 0x7FFFFFFF
|
|
|
|
def toString(self) -> str:
|
|
return f"WifiP2pDevice(name={self.deviceName}, addr={self.deviceAddress}, status={self.status})"
|
|
|
|
|
|
class WifiP2pGroup(Stub):
|
|
"""WifiP2pGroup — WiFi P2P 组"""
|
|
|
|
def __init__(self):
|
|
super().__init__()
|
|
self._network_name: Optional[str] = None
|
|
self._owner: Optional[WifiP2pDevice] = None
|
|
self._is_group_owner = False
|
|
self._passphrase: Optional[str] = None
|
|
self._interface: Optional[str] = None
|
|
self._clients: List[WifiP2pDevice] = []
|
|
self._frequency = 0
|
|
|
|
def getNetworkName(self) -> Optional[str]:
|
|
return self._network_name
|
|
|
|
def isGroupOwner(self) -> bool:
|
|
return self._is_group_owner
|
|
|
|
def getOwner(self) -> Optional[WifiP2pDevice]:
|
|
return self._owner
|
|
|
|
def getPassphrase(self) -> Optional[str]:
|
|
return self._passphrase
|
|
|
|
def getInterface(self) -> Optional[str]:
|
|
return self._interface
|
|
|
|
def getClientList(self) -> List[WifiP2pDevice]:
|
|
return list(self._clients)
|
|
|
|
def getFrequency(self) -> int:
|
|
return self._frequency
|
|
|
|
def addClient(self, device: WifiP2pDevice) -> None:
|
|
if device not in self._clients:
|
|
self._clients.append(device)
|
|
|
|
def removeClient(self, device: WifiP2pDevice) -> None:
|
|
if device in self._clients:
|
|
self._clients.remove(device)
|
|
|
|
def toString(self) -> str:
|
|
return f"WifiP2pGroup(net={self._network_name}, clients={len(self._clients)})"
|
|
|
|
|
|
class WifiP2pConfig(Stub):
|
|
"""WifiP2pConfig — WiFi P2P 配置"""
|
|
|
|
class Builder(Stub):
|
|
"""WifiP2pConfig.Builder — 构建器"""
|
|
|
|
def __init__(self):
|
|
super().__init__()
|
|
self._config = WifiP2pConfig()
|
|
|
|
def setDeviceAddress(self, address: str) -> "WifiP2pConfig.Builder":
|
|
self._config._device_address = address
|
|
return self
|
|
|
|
def setDeviceName(self, name: str) -> "WifiP2pConfig.Builder":
|
|
self._config._device_name = name
|
|
return self
|
|
|
|
def setGroupOwnerIntent(self, intent: int) -> "WifiP2pConfig.Builder":
|
|
self._config._group_owner_intent = intent
|
|
return self
|
|
|
|
def setNetworkName(self, name: str) -> "WifiP2pConfig.Builder":
|
|
self._config._network_name = name
|
|
return self
|
|
|
|
def setPassphrase(self, passphrase: str) -> "WifiP2pConfig.Builder":
|
|
self._config._passphrase = passphrase
|
|
return self
|
|
|
|
def enablePersistentMode(self, enabled: bool) -> "WifiP2pConfig.Builder":
|
|
self._config._persistent_mode = enabled
|
|
return self
|
|
|
|
def build(self) -> "WifiP2pConfig":
|
|
return self._config
|
|
|
|
def __init__(self):
|
|
super().__init__()
|
|
self._device_address: Optional[str] = None
|
|
self._device_name: Optional[str] = None
|
|
self._group_owner_intent = -1
|
|
self._network_name: Optional[str] = None
|
|
self._passphrase: Optional[str] = None
|
|
self._persistent_mode = False
|
|
self._wps_config = 0
|
|
self._net_id = -1
|
|
|
|
def getDeviceAddress(self) -> Optional[str]:
|
|
return self._device_address
|
|
|
|
def getDeviceName(self) -> Optional[str]:
|
|
return self._device_name
|
|
|
|
def getGroupOwnerIntent(self) -> int:
|
|
return self._group_owner_intent
|
|
|
|
def isPersistentMode(self) -> bool:
|
|
return self._persistent_mode
|
|
|
|
def toString(self) -> str:
|
|
return f"WifiP2pConfig(addr={self._device_address}, name={self._device_name})"
|
|
|
|
|
|
class WifiP2pManager(Stub):
|
|
"""WifiP2pManager — WiFi P2P 管理器"""
|
|
|
|
WIFI_P2P_STATE_ENABLED = 2
|
|
WIFI_P2P_STATE_DISABLED = 1
|
|
WIFI_P2P_PEERS_CHANGED_ACTION = "android.net.wifi.p2p.PEERS_CHANGED"
|
|
WIFI_P2P_STATE_CHANGED_ACTION = "android.net.wifi.p2p.STATE_CHANGED"
|
|
WIFI_P2P_CONNECTION_CHANGED_ACTION = "android.net.wifi.p2p.CONNECTION_STATE_CHANGE"
|
|
WIFI_P2P_THIS_DEVICE_CHANGED_ACTION = "android.net.wifi.p2p.THIS_DEVICE_CHANGED"
|
|
WIFI_P2P_DISCOVERY_CHANGED_ACTION = "android.net.wifi.p2p.DISCOVERY_STATE_CHANGE"
|
|
WIFI_P2P_PERSISTENT_GROUPS_CHANGED_ACTION = "android.net.wifi.p2p.PERSISTENT_GROUPS_CHANGED"
|
|
|
|
BUSY = 2
|
|
ERROR = 0
|
|
P2P_UNSUPPORTED = 1
|
|
NO_SERVICE_REQUESTS = 3
|
|
|
|
def __init__(self, context: Any = None):
|
|
super().__init__()
|
|
self._context = context
|
|
self._peers: List[WifiP2pDevice] = []
|
|
self._services: List[Any] = []
|
|
self._discovery_running = False
|
|
self._this_device: Optional[WifiP2pDevice] = None
|
|
self._groups: List[WifiP2pGroup] = []
|
|
self._listeners: Dict[str, List[Any]] = {}
|
|
|
|
def initialize(self, context: Any, looper: Any, listener: Any) -> "WifiP2pManager":
|
|
return self
|
|
|
|
def discoverPeers(self, channel: Any, listener: Any) -> None:
|
|
self._discovery_running = True
|
|
if listener:
|
|
listener.onSuccess()
|
|
|
|
def stopPeerDiscovery(self, channel: Any, listener: Any) -> None:
|
|
self._discovery_running = False
|
|
if listener:
|
|
listener.onSuccess()
|
|
|
|
def requestPeers(self, channel: Any, listener: Any) -> None:
|
|
if listener:
|
|
listener.onPeersAvailable(self._peers)
|
|
|
|
def connect(self, channel: Any, config: WifiP2pConfig, listener: Any) -> None:
|
|
if listener:
|
|
listener.onSuccess()
|
|
|
|
def cancelConnect(self, channel: Any, listener: Any) -> None:
|
|
if listener:
|
|
listener.onSuccess()
|
|
|
|
def createGroup(self, channel: Any, listener: Any) -> None:
|
|
if listener:
|
|
listener.onSuccess()
|
|
|
|
def removeGroup(self, channel: Any, listener: Any) -> None:
|
|
if listener:
|
|
listener.onSuccess()
|
|
|
|
def requestGroupInfo(self, channel: Any, listener: Any) -> None:
|
|
if listener and self._groups:
|
|
listener.onGroupInfoAvailable(self._groups[0] if self._groups else None)
|
|
|
|
def requestConnectionInfo(self, channel: Any, listener: Any) -> None:
|
|
if listener:
|
|
listener.onConnectionInfoAvailable(None)
|
|
|
|
def setDeviceName(self, channel: Any, deviceName: str, listener: Any) -> None:
|
|
if listener:
|
|
listener.onSuccess()
|
|
|
|
def setWpsPbc(self, channel: Any, iface: str, listener: Any) -> None:
|
|
if listener:
|
|
listener.onSuccess()
|
|
|
|
def setWpsPin(self, channel: Any, iface: str, pin: str, listener: Any) -> None:
|
|
if listener:
|
|
listener.onSuccess()
|
|
|
|
def getAvailableServiceInfo(self, device: WifiP2pDevice) -> Optional[Any]:
|
|
return None
|
|
|
|
def addServiceRequest(self, channel: Any, req: Any, listener: Any) -> None:
|
|
if listener:
|
|
listener.onSuccess()
|
|
|
|
def removeServiceRequest(self, channel: Any, req: Any, listener: Any) -> None:
|
|
if listener:
|
|
listener.onSuccess()
|
|
|
|
def setServiceResponseListener(self, channel: Any, listener: Any) -> None:
|
|
pass
|
|
|
|
def clearServiceResponses(self, channel: Any, listener: Any) -> None:
|
|
if listener:
|
|
listener.onSuccess()
|
|
|
|
def clearLocalServices(self, channel: Any, listener: Any) -> None:
|
|
if listener:
|
|
listener.onSuccess()
|
|
|
|
def requestServiceInfo(self, channel: Any, device: WifiP2pDevice, listener: Any) -> None:
|
|
if listener:
|
|
listener.onServiceInfoAvailable(None)
|
|
|
|
def getWifiP2pDeviceList(self) -> List[WifiP2pDevice]:
|
|
return list(self._peers)
|
|
|
|
def isDiscoveryRunning(self) -> bool:
|
|
return self._discovery_running
|
|
|
|
def toString(self) -> str:
|
|
return f"WifiP2pManager(peers={len(self._peers)}, discovery={self._discovery_running})"
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# WindowManager
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class WindowManager(Stub):
|
|
"""WindowManager — 窗口管理器"""
|
|
|
|
# LayoutParams 类型
|
|
TYPE_BASE_APPLICATION = 1
|
|
TYPE_APPLICATION = 2
|
|
TYPE_APPLICATION_STARTING = 3
|
|
TYPE_APPLICATION_PANEL = 1000
|
|
TYPE_APPLICATION_MEDIA = 1001
|
|
TYPE_APPLICATION_SUB_PANEL = 1002
|
|
TYPE_APPLICATION_ATTACHED_DIALOG = 1003
|
|
TYPE_APPLICATION_OVERLAY = 1004
|
|
TYPE_STATUS_BAR = 2000
|
|
TYPE_SYSTEM_ALERT = 2003
|
|
TYPE_SYSTEM_OVERLAY = 2006
|
|
TYPE_TOAST = 2005
|
|
TYPE_PHONE = 2002
|
|
TYPE_PRIORITY_PHONE = 2007
|
|
TYPE_SYSTEM_DIALOG = 2008
|
|
TYPE_KEYGUARD = 2004
|
|
TYPE_INPUT_METHOD = 2011
|
|
TYPE_INPUT_METHOD_DIALOG = 2012
|
|
TYPE_WALLPAPER = 2013
|
|
TYPE_NAVIGATION_BAR = 2019
|
|
TYPE_DREAM = 2024
|
|
TYPE_ACCESSIBILITY_OVERLAY = 2032
|
|
TYPE_VOLUME_OVERLAY = 2033
|
|
TYPE_SECURE_SYSTEM_OVERLAY = 2034
|
|
|
|
# LayoutParams 标志
|
|
FLAG_ALLOW_LOCK_WHILE_SCREEN_ON = 0x00000001
|
|
FLAG_DIM_BEHIND = 0x00000002
|
|
FLAG_BLUR_BEHIND = 0x00000004
|
|
FLAG_NOT_FOCUSABLE = 0x00000008
|
|
FLAG_NOT_TOUCHABLE = 0x00000010
|
|
FLAG_NOT_TOUCH_MODAL = 0x00000020
|
|
FLAG_TOUCHABLE_WHEN_WAKING = 0x00000040
|
|
FLAG_KEEP_SCREEN_ON = 0x00000080
|
|
FLAG_LAYOUT_IN_SCREEN = 0x00000100
|
|
FLAG_LAYOUT_NO_LIMITS = 0x00000200
|
|
FLAG_FULLSCREEN = 0x00000400
|
|
FLAG_FORCE_NOT_FULLSCREEN = 0x00000800
|
|
FLAG_DITHER = 0x00001000
|
|
FLAG_SECURE = 0x00002000
|
|
FLAG_SCALED = 0x00004000
|
|
FLAG_IGNORE_CHEEK_PRESSES = 0x00008000
|
|
FLAG_LAYOUT_INSET_DECOR = 0x00010000
|
|
FLAG_ALT_FOCUSABLE_IM = 0x00020000
|
|
FLAG_WATCH_OUTSIDE_TOUCH = 0x00040000
|
|
FLAG_SHOW_WHEN_LOCKED = 0x00080000
|
|
FLAG_SHOW_WALLPAPER = 0x00100000
|
|
FLAG_TURN_SCREEN_ON = 0x00200000
|
|
FLAG_DISMISS_KEYGUARD = 0x00400000
|
|
FLAG_SPLIT_TOUCH = 0x00800000
|
|
FLAG_HARDWARE_ACCELERATED = 0x01000000
|
|
FLAG_LOCAL_FOCUS_MODE = 0x10000000
|
|
FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS = 0x20000000
|
|
FLAG_TRANSLUCENT_STATUS = 0x04000000
|
|
FLAG_TRANSLUCENT_NAVIGATION = 0x08000000
|
|
|
|
# 软输入模式
|
|
SOFT_INPUT_STATE_UNSPECIFIED = 0
|
|
SOFT_INPUT_STATE_UNCHANGED = 1
|
|
SOFT_INPUT_STATE_HIDDEN = 2
|
|
SOFT_INPUT_STATE_ALWAYS_HIDDEN = 3
|
|
SOFT_INPUT_STATE_VISIBLE = 4
|
|
SOFT_INPUT_STATE_ALWAYS_VISIBLE = 5
|
|
SOFT_INPUT_ADJUST_RESIZE = 0x10
|
|
SOFT_INPUT_ADJUST_PAN = 0x20
|
|
SOFT_INPUT_ADJUST_NOTHING = 0x30
|
|
SOFT_INPUT_ADJUST_UNSPECIFIED = 0x00
|
|
SOFT_INPUT_IS_FORWARD_NAVIGATION = 0x100
|
|
|
|
INVALID_DISPLAY = -1
|
|
DOCKED_INVALID = -1
|
|
DOCKED_LEFT = 1
|
|
DOCKED_TOP = 2
|
|
DOCKED_RIGHT = 3
|
|
DOCKED_BOTTOM = 4
|
|
|
|
class LayoutParams(Stub):
|
|
"""WindowManager.LayoutParams — 窗口布局参数"""
|
|
|
|
MATCH_PARENT = -1
|
|
WRAP_CONTENT = -2
|
|
|
|
def __init__(self, w: int = -1, h: int = -1, type_: int = 2, flags: int = 0):
|
|
super().__init__()
|
|
self.width = w
|
|
self.height = h
|
|
self.type = type_
|
|
self.flags = flags
|
|
self.x = 0
|
|
self.y = 0
|
|
self.horizontalWeight = 0.0
|
|
self.verticalWeight = 0.0
|
|
self.horizontalMargin = 0.0
|
|
self.verticalMargin = 0.0
|
|
self.gravity = 0
|
|
self.softInputMode = WindowManager.SOFT_INPUT_STATE_UNSPECIFIED
|
|
self.windowAnimations = -1
|
|
self.alpha = 1.0
|
|
self.dimAmount = 0.0
|
|
self.screenOrientation = -1
|
|
self.screenBrightness = -1.0
|
|
self.buttonBrightness = -1.0
|
|
self.token: Optional[Any] = None
|
|
self.packageName: Optional[str] = None
|
|
self.format = -1
|
|
self.systemUiVisibility = 0
|
|
self.subtreeSystemUiVisibility = 0
|
|
self.preferredRefreshRate: float = 0.0
|
|
self.colorMode = 0
|
|
|
|
def toString(self) -> str:
|
|
return f"LayoutParams({self.width}x{self.height}, type={self.type}, flags=0x{self.flags:x})"
|
|
|
|
def __init__(self, context: Any = None):
|
|
super().__init__()
|
|
self._context = context
|
|
self._default_display: Optional[Any] = None
|
|
self._current_window_focus: Optional[Any] = None
|
|
self._window_views: List[Any] = []
|
|
|
|
def getDefaultDisplay(self) -> Optional[Any]:
|
|
return self._default_display
|
|
|
|
def getCurrentWindowFocus(self) -> Optional[Any]:
|
|
return self._current_window_focus
|
|
|
|
def addView(self, view: Any, params: "WindowManager.LayoutParams") -> None:
|
|
self._window_views.append((view, params))
|
|
|
|
def updateViewLayout(self, view: Any, params: "WindowManager.LayoutParams") -> None:
|
|
for i, (v, p) in enumerate(self._window_views):
|
|
if v is view:
|
|
self._window_views[i] = (view, params)
|
|
break
|
|
|
|
def removeView(self, view: Any) -> None:
|
|
self._window_views = [(v, p) for v, p in self._window_views if v is not view]
|
|
|
|
def removeViewImmediate(self, view: Any) -> None:
|
|
self.removeView(view)
|
|
|
|
def getWindowViews(self) -> List[Any]:
|
|
return [v for v, _ in self._window_views]
|
|
|
|
def toString(self) -> str:
|
|
return f"WindowManager(views={len(self._window_views)})"
|
|
|
|
|
|
WindowManager_LayoutParams = WindowManager.LayoutParams |