- android/ 167个模块 (app/content/os/view/widget/graphics/media/hardware/net/telephony/provider等) - java/ 35个模块 (lang/io/util/net/nio/security/crypto/sql/beans/rmi/awt等) - javax/ 4个模块 (net/crypto/security/sql) - org/ 5个模块 (json/w3c_dom/xml_sax/xml_pull/apache_http) - dalvik/ 1个模块 (system) - ~3053个类/接口,方法签名完全对齐Android SDK - 桌面跨平台运行 (Windows/macOS/Linux) - 修复所有导入错误和Python关键字冲突
551 lines
19 KiB
Python
551 lines
19 KiB
Python
"""
|
|
Android OverlayManager API — OverlayManager, OverlayInfo, OverlayManagerTransaction, OverlayStore
|
|
方法签名完全对齐 Android SDK
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
import time
|
|
import json
|
|
import uuid
|
|
import threading
|
|
from typing import Any, Dict, List, Optional, Set, Tuple
|
|
|
|
from .._core import Stub, AndroidOnlyError
|
|
from ..java.lang import RuntimeException
|
|
|
|
IllegalArgumentException = type("IllegalArgumentException", (RuntimeException,), {})
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# 常量
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
# CATEGORY_* 常量
|
|
CATEGORY_ALL = "android.overlay.category.ALL"
|
|
CATEGORY_FONT = "android.overlay.category.FONT"
|
|
CATEGORY_THEME = "android.overlay.category.THEME"
|
|
CATEGORY_ICON = "android.overlay.category.ICON"
|
|
CATEGORY_ICON_OVERLAY = "android.overlay.category.ICON_OVERLAY"
|
|
CATEGORY_SOUND = "android.overlay.category.SOUND"
|
|
CATEGORY_BOOT_ANIMATION = "android.overlay.category.BOOT_ANIMATION"
|
|
CATEGORY_WALLPAPER = "android.overlay.category.WALLPAPER"
|
|
CATEGORY_DYNAMIC = "android.overlay.category.DYNAMIC"
|
|
CATEGORY_RRO = "android.overlay.category.RRO"
|
|
CATEGORY_STATIC = "android.overlay.category.STATIC"
|
|
|
|
# STATE_* 常量
|
|
STATE_UNKNOWN = 0
|
|
STATE_NOT_INSTALLED = 1
|
|
STATE_INSTALLED = 2
|
|
STATE_ENABLED = 3
|
|
STATE_DISABLED = 4
|
|
STATE_ENABLEMENT_DISABLED = 5
|
|
STATE_ENABLEMENT_ENABLED = 6
|
|
STATE_ENABLEMENT_UNKNOWN = 7
|
|
STATE_OVERLAY_NOT_FOUND = 8
|
|
STATE_OVERLAY_UPGRADING = 9
|
|
STATE_OVERLAY_REMOVED = 10
|
|
STATE_PACKAGE_INSTALLED = 11
|
|
STATE_PACKAGE_UPDATED = 12
|
|
STATE_PACKAGE_REMOVED = 13
|
|
STATE_TARGET_PACKAGE_CHANGED = 14
|
|
STATE_MISSING_TARGET_PACKAGE = 15
|
|
STATE_UPGRADE_PENDING = 16
|
|
|
|
# FLAG_* 常量
|
|
FLAG_ENABLE = 0x00000001
|
|
FLAG_DISABLE = 0x00000002
|
|
FLAG_REMOVE = 0x00000004
|
|
FLAG_UPGRADE = 0x00000008
|
|
FLAG_INSTALL = 0x00000010
|
|
FLAG_IMMUTABLE = 0x00000020
|
|
FLAG_SYSTEM = 0x00000040
|
|
FLAG_STATIC_OVERLAY = 0x00000080
|
|
FLAG_DYNAMIC_OVERLAY = 0x00000100
|
|
FLAG_FIRST_TARGET = 0x00000200
|
|
FLAG_LAST_TARGET = 0x00000400
|
|
FLAG_EXTERNAL = 0x00000800
|
|
FLAG_PERSISTENT = 0x00001000
|
|
|
|
# PRIORITY_ORDER 常量
|
|
PRIORITY_ORDER_UNDEFINED = 0
|
|
PRIORITY_ORDER_LOWEST = 1
|
|
PRIORITY_ORDER_LOW = 2
|
|
PRIORITY_ORDER_MEDIUM = 3
|
|
PRIORITY_ORDER_HIGH = 4
|
|
PRIORITY_ORDER_HIGHEST = 5
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# OverlayInfo
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class OverlayInfo(Stub):
|
|
"""OverlayInfo — 覆盖层信息"""
|
|
|
|
CATEGORY_ALL = CATEGORY_ALL
|
|
CATEGORY_FONT = CATEGORY_FONT
|
|
CATEGORY_THEME = CATEGORY_THEME
|
|
CATEGORY_ICON = CATEGORY_ICON
|
|
CATEGORY_ICON_OVERLAY = CATEGORY_ICON_OVERLAY
|
|
CATEGORY_SOUND = CATEGORY_SOUND
|
|
CATEGORY_BOOT_ANIMATION = CATEGORY_BOOT_ANIMATION
|
|
CATEGORY_WALLPAPER = CATEGORY_WALLPAPER
|
|
CATEGORY_DYNAMIC = CATEGORY_DYNAMIC
|
|
|
|
STATE_UNKNOWN = STATE_UNKNOWN
|
|
STATE_NOT_INSTALLED = STATE_NOT_INSTALLED
|
|
STATE_INSTALLED = STATE_INSTALLED
|
|
STATE_ENABLED = STATE_ENABLED
|
|
STATE_DISABLED = STATE_DISABLED
|
|
STATE_ENABLEMENT_DISABLED = STATE_ENABLEMENT_DISABLED
|
|
STATE_ENABLEMENT_ENABLED = STATE_ENABLEMENT_ENABLED
|
|
STATE_ENABLEMENT_UNKNOWN = STATE_ENABLEMENT_UNKNOWN
|
|
STATE_OVERLAY_NOT_FOUND = STATE_OVERLAY_NOT_FOUND
|
|
STATE_OVERLAY_UPGRADING = STATE_OVERLAY_UPGRADING
|
|
STATE_PACKAGE_INSTALLED = STATE_PACKAGE_INSTALLED
|
|
STATE_PACKAGE_UPDATED = STATE_PACKAGE_UPDATED
|
|
STATE_PACKAGE_REMOVED = STATE_PACKAGE_REMOVED
|
|
STATE_TARGET_PACKAGE_CHANGED = STATE_TARGET_PACKAGE_CHANGED
|
|
STATE_UPGRADE_PENDING = STATE_UPGRADE_PENDING
|
|
|
|
def __init__(
|
|
self,
|
|
packageName: str = "",
|
|
targetPackageName: str = "",
|
|
category: str = CATEGORY_THEME,
|
|
state: int = STATE_UNKNOWN,
|
|
):
|
|
super().__init__()
|
|
self._package_name = packageName
|
|
self._target_package_name = targetPackageName
|
|
self._category = category
|
|
self._state = state
|
|
self._is_enabled = (state == STATE_ENABLED or state == STATE_ENABLEMENT_ENABLED)
|
|
self._priority = 0
|
|
self._is_static = False
|
|
self._is_upgradable = False
|
|
self._is_system = False
|
|
self._version = 0
|
|
self._config: Optional[str] = None
|
|
self._label: Optional[str] = None
|
|
self._icon: Optional[Any] = None
|
|
self._fabricated = False
|
|
self._overlay_path: Optional[str] = None
|
|
self._target_overlayable_name: Optional[str] = None
|
|
self._require_all = False
|
|
self._overlay_category: Optional[str] = category
|
|
self._base_path: Optional[str] = None
|
|
self._overlay_id = str(uuid.uuid4())
|
|
self._install_time = time.time()
|
|
self._mod_time = time.time()
|
|
|
|
def getPackageName(self) -> str:
|
|
return self._package_name
|
|
|
|
def getTargetPackageName(self) -> str:
|
|
return self._target_package_name
|
|
|
|
def getCategory(self) -> str:
|
|
return self._category
|
|
|
|
def getState(self) -> int:
|
|
return self._state
|
|
|
|
def setState(self, state: int) -> None:
|
|
self._state = state
|
|
self._is_enabled = (state == STATE_ENABLED)
|
|
|
|
def isEnabled(self) -> bool:
|
|
return self._is_enabled
|
|
|
|
def getPriority(self) -> int:
|
|
return self._priority
|
|
|
|
def setPriority(self, priority: int) -> None:
|
|
self._priority = priority
|
|
|
|
def isStatic(self) -> bool:
|
|
return self._is_static
|
|
|
|
def isUpgradable(self) -> bool:
|
|
return self._is_upgradable
|
|
|
|
def isSystem(self) -> bool:
|
|
return self._is_system
|
|
|
|
def getVersion(self) -> int:
|
|
return self._version
|
|
|
|
def getLabel(self) -> Optional[str]:
|
|
return self._label
|
|
|
|
def getIcon(self) -> Optional[Any]:
|
|
return self._icon
|
|
|
|
def isFabricated(self) -> bool:
|
|
return self._fabricated
|
|
|
|
def getOverlayPath(self) -> Optional[str]:
|
|
return self._overlay_path
|
|
|
|
def getTargetOverlayableName(self) -> Optional[str]:
|
|
return self._target_overlayable_name
|
|
|
|
def getOverlayId(self) -> str:
|
|
return self._overlay_id
|
|
|
|
def getInstallTime(self) -> float:
|
|
return self._install_time
|
|
|
|
def getModTime(self) -> float:
|
|
return self._mod_time
|
|
|
|
def getConfig(self) -> Optional[str]:
|
|
return self._config
|
|
|
|
def requiresAll(self) -> bool:
|
|
return self._require_all
|
|
|
|
def toString(self) -> str:
|
|
return (
|
|
f"OverlayInfo(package={self._package_name}, "
|
|
f"target={self._target_package_name}, "
|
|
f"category={self._category}, "
|
|
f"state={self._state})"
|
|
)
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# OverlayManagerTransaction
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class OverlayManagerTransaction(Stub):
|
|
"""OverlayManagerTransaction — 覆盖层管理器事务"""
|
|
|
|
TYPE_UNKNOWN = 0
|
|
TYPE_SET_ENABLED = 1
|
|
TYPE_SET_DISABLED = 2
|
|
TYPE_REGISTER = 3
|
|
TYPE_UNREGISTER = 4
|
|
TYPE_SET_PRIORITY = 5
|
|
TYPE_SET_CATEGORY = 6
|
|
TYPE_SET_TARGET = 7
|
|
TYPE_REMOVE = 8
|
|
TYPE_SET_STATE = 9
|
|
|
|
def __init__(self):
|
|
super().__init__()
|
|
self._operations: List[Dict[str, Any]] = []
|
|
self._transaction_id = str(uuid.uuid4())
|
|
self._created_at = time.time()
|
|
self._committed = False
|
|
self._rollback_on_failure = True
|
|
|
|
def setEnabled(self, packageName: str, enabled: bool) -> "OverlayManagerTransaction":
|
|
self._operations.append({
|
|
"type": OverlayManagerTransaction.TYPE_SET_ENABLED,
|
|
"packageName": packageName,
|
|
"enabled": enabled,
|
|
})
|
|
return self
|
|
|
|
def setDisabled(self, packageName: str) -> "OverlayManagerTransaction":
|
|
self._operations.append({
|
|
"type": OverlayManagerTransaction.TYPE_SET_DISABLED,
|
|
"packageName": packageName,
|
|
})
|
|
return self
|
|
|
|
def registerOverlay(self, packageName: str) -> "OverlayManagerTransaction":
|
|
self._operations.append({
|
|
"type": OverlayManagerTransaction.TYPE_REGISTER,
|
|
"packageName": packageName,
|
|
})
|
|
return self
|
|
|
|
def unregisterOverlay(self, packageName: str) -> "OverlayManagerTransaction":
|
|
self._operations.append({
|
|
"type": OverlayManagerTransaction.TYPE_UNREGISTER,
|
|
"packageName": packageName,
|
|
})
|
|
return self
|
|
|
|
def setPriority(self, packageName: str, priority: int) -> "OverlayManagerTransaction":
|
|
self._operations.append({
|
|
"type": OverlayManagerTransaction.TYPE_SET_PRIORITY,
|
|
"packageName": packageName,
|
|
"priority": priority,
|
|
})
|
|
return self
|
|
|
|
def setCategory(self, packageName: str, category: str) -> "OverlayManagerTransaction":
|
|
self._operations.append({
|
|
"type": OverlayManagerTransaction.TYPE_SET_CATEGORY,
|
|
"packageName": packageName,
|
|
"category": category,
|
|
})
|
|
return self
|
|
|
|
def setTarget(self, packageName: str, target: str) -> "OverlayManagerTransaction":
|
|
self._operations.append({
|
|
"type": OverlayManagerTransaction.TYPE_SET_TARGET,
|
|
"packageName": packageName,
|
|
"target": target,
|
|
})
|
|
return self
|
|
|
|
def removeOverlay(self, packageName: str) -> "OverlayManagerTransaction":
|
|
self._operations.append({
|
|
"type": OverlayManagerTransaction.TYPE_REMOVE,
|
|
"packageName": packageName,
|
|
})
|
|
return self
|
|
|
|
def getOperations(self) -> List[Dict[str, Any]]:
|
|
return list(self._operations)
|
|
|
|
def getTransactionId(self) -> str:
|
|
return self._transaction_id
|
|
|
|
def isCommitted(self) -> bool:
|
|
return self._committed
|
|
|
|
def getOperationCount(self) -> int:
|
|
return len(self._operations)
|
|
|
|
def toString(self) -> str:
|
|
return f"OverlayManagerTransaction(ops={len(self._operations)}, committed={self._committed})"
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# OverlayStore
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class OverlayStore(Stub):
|
|
"""OverlayStore — 覆盖层存储"""
|
|
|
|
def __init__(self):
|
|
super().__init__()
|
|
self._overlays: Dict[str, OverlayInfo] = {}
|
|
self._lock = threading.Lock()
|
|
self._store_path: Optional[str] = None
|
|
self._max_overlays = 100
|
|
self._persist_enabled = False
|
|
|
|
def getOverlay(self, packageName: str) -> Optional[OverlayInfo]:
|
|
with self._lock:
|
|
return self._overlays.get(packageName)
|
|
|
|
def getAllOverlays(self) -> List[OverlayInfo]:
|
|
with self._lock:
|
|
return list(self._overlays.values())
|
|
|
|
def getOverlaysForTarget(self, targetPackage: str) -> List[OverlayInfo]:
|
|
with self._lock:
|
|
return [
|
|
info for info in self._overlays.values()
|
|
if info.getTargetPackageName() == targetPackage
|
|
]
|
|
|
|
def getOverlaysByCategory(self, category: str) -> List[OverlayInfo]:
|
|
with self._lock:
|
|
return [
|
|
info for info in self._overlays.values()
|
|
if info.getCategory() == category
|
|
]
|
|
|
|
def addOverlay(self, info: OverlayInfo) -> None:
|
|
with self._lock:
|
|
self._overlays[info.getPackageName()] = info
|
|
|
|
def removeOverlay(self, packageName: str) -> Optional[OverlayInfo]:
|
|
with self._lock:
|
|
return self._overlays.pop(packageName, None)
|
|
|
|
def updateOverlay(self, packageName: str, info: OverlayInfo) -> bool:
|
|
with self._lock:
|
|
if packageName in self._overlays:
|
|
self._overlays[packageName] = info
|
|
return True
|
|
return False
|
|
|
|
def contains(self, packageName: str) -> bool:
|
|
with self._lock:
|
|
return packageName in self._overlays
|
|
|
|
def getEnabledOverlays(self) -> List[OverlayInfo]:
|
|
with self._lock:
|
|
return [info for info in self._overlays.values() if info.isEnabled()]
|
|
|
|
def getDisabledOverlays(self) -> List[OverlayInfo]:
|
|
with self._lock:
|
|
return [info for info in self._overlays.values() if not info.isEnabled()]
|
|
|
|
def getStaticOverlays(self) -> List[OverlayInfo]:
|
|
with self._lock:
|
|
return [info for info in self._overlays.values() if info.isStatic()]
|
|
|
|
def getOverlayCount(self) -> int:
|
|
with self._lock:
|
|
return len(self._overlays)
|
|
|
|
def clear(self) -> None:
|
|
with self._lock:
|
|
self._overlays.clear()
|
|
|
|
def toString(self) -> str:
|
|
with self._lock:
|
|
return f"OverlayStore(overlays={len(self._overlays)})"
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# OverlayManager
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class OverlayManager(Stub):
|
|
"""OverlayManager — 覆盖层管理器 (桌面存根)"""
|
|
|
|
CATEGORY_ALL = CATEGORY_ALL
|
|
CATEGORY_FONT = CATEGORY_FONT
|
|
CATEGORY_THEME = CATEGORY_THEME
|
|
CATEGORY_ICON = CATEGORY_ICON
|
|
CATEGORY_SOUND = CATEGORY_SOUND
|
|
|
|
FLAG_ENABLE = FLAG_ENABLE
|
|
FLAG_DISABLE = FLAG_DISABLE
|
|
FLAG_REMOVE = FLAG_REMOVE
|
|
FLAG_UPGRADE = FLAG_UPGRADE
|
|
FLAG_INSTALL = FLAG_INSTALL
|
|
FLAG_IMMUTABLE = FLAG_IMMUTABLE
|
|
FLAG_SYSTEM = FLAG_SYSTEM
|
|
FLAG_STATIC_OVERLAY = FLAG_STATIC_OVERLAY
|
|
FLAG_DYNAMIC_OVERLAY = FLAG_DYNAMIC_OVERLAY
|
|
FLAG_EXTERNAL = FLAG_EXTERNAL
|
|
FLAG_PERSISTENT = FLAG_PERSISTENT
|
|
|
|
STATE_UNKNOWN = STATE_UNKNOWN
|
|
STATE_NOT_INSTALLED = STATE_NOT_INSTALLED
|
|
STATE_INSTALLED = STATE_INSTALLED
|
|
STATE_ENABLED = STATE_ENABLED
|
|
STATE_DISABLED = STATE_DISABLED
|
|
STATE_ENABLEMENT_DISABLED = STATE_ENABLEMENT_DISABLED
|
|
STATE_ENABLEMENT_ENABLED = STATE_ENABLEMENT_ENABLED
|
|
STATE_ENABLEMENT_UNKNOWN = STATE_ENABLEMENT_UNKNOWN
|
|
STATE_OVERLAY_NOT_FOUND = STATE_OVERLAY_NOT_FOUND
|
|
STATE_OVERLAY_UPGRADING = STATE_OVERLAY_UPGRADING
|
|
|
|
def __init__(self, context: Any = None):
|
|
super().__init__()
|
|
self._context = context
|
|
self._store = OverlayStore()
|
|
self._lock = threading.Lock()
|
|
self._transaction_history: List[OverlayManagerTransaction] = []
|
|
self._callbacks: Dict[str, List[Callable]] = {}
|
|
self._is_available = True
|
|
|
|
def getOverlayInfo(self, packageName: str) -> Optional[OverlayInfo]:
|
|
with self._lock:
|
|
return self._store.getOverlay(packageName)
|
|
|
|
def getAllOverlays(self) -> List[OverlayInfo]:
|
|
with self._lock:
|
|
return self._store.getAllOverlays()
|
|
|
|
def getOverlaysForTarget(self, targetPackage: str) -> List[OverlayInfo]:
|
|
with self._lock:
|
|
return self._store.getOverlaysForTarget(targetPackage)
|
|
|
|
def setEnabled(self, packageName: str, enabled: bool, userId: int = 0) -> None:
|
|
with self._lock:
|
|
info = self._store.getOverlay(packageName)
|
|
if info:
|
|
new_state = STATE_ENABLED if enabled else STATE_DISABLED
|
|
info.setState(new_state)
|
|
|
|
def setEnabledExclusive(
|
|
self, packageName: str, withinCategory: bool, userId: int = 0
|
|
) -> None:
|
|
with self._lock:
|
|
info = self._store.getOverlay(packageName)
|
|
if info:
|
|
info.setState(STATE_ENABLED)
|
|
category = info.getCategory()
|
|
for overlay in self._store.getAllOverlays():
|
|
if overlay.getPackageName() != packageName:
|
|
if withinCategory and overlay.getCategory() == category:
|
|
overlay.setState(STATE_DISABLED)
|
|
elif not withinCategory:
|
|
overlay.setState(STATE_DISABLED)
|
|
|
|
def isEnabled(self, packageName: str) -> bool:
|
|
with self._lock:
|
|
info = self._store.getOverlay(packageName)
|
|
return info is not None and info.isEnabled()
|
|
|
|
def commit(
|
|
self, transaction: OverlayManagerTransaction
|
|
) -> None:
|
|
with self._lock:
|
|
for op in transaction.getOperations():
|
|
op_type = op.get("type")
|
|
pkg = op.get("packageName", "")
|
|
if op_type == OverlayManagerTransaction.TYPE_SET_ENABLED:
|
|
self.setEnabled(pkg, op.get("enabled", True))
|
|
elif op_type == OverlayManagerTransaction.TYPE_SET_DISABLED:
|
|
self.setEnabled(pkg, False)
|
|
elif op_type == OverlayManagerTransaction.TYPE_REGISTER:
|
|
info = OverlayInfo(packageName=pkg)
|
|
self._store.addOverlay(info)
|
|
elif op_type == OverlayManagerTransaction.TYPE_UNREGISTER:
|
|
self._store.removeOverlay(pkg)
|
|
elif op_type == OverlayManagerTransaction.TYPE_SET_PRIORITY:
|
|
info = self._store.getOverlay(pkg)
|
|
if info:
|
|
info.setPriority(op.get("priority", 0))
|
|
elif op_type == OverlayManagerTransaction.TYPE_REMOVE:
|
|
self._store.removeOverlay(pkg)
|
|
self._transaction_history.append(transaction)
|
|
|
|
def getDefaultOverlayPackages(self) -> List[str]:
|
|
return []
|
|
|
|
def getOverlayInfosForTarget(self, targetPackage: str, userId: int = 0) -> List[OverlayInfo]:
|
|
return self.getOverlaysForTarget(targetPackage)
|
|
|
|
def getOverlayStore(self) -> OverlayStore:
|
|
return self._store
|
|
|
|
def registerCallback(self, callback: Any) -> None:
|
|
pass
|
|
|
|
def unregisterCallback(self, callback: Any) -> None:
|
|
pass
|
|
|
|
def onOverlayChanged(self, packageName: str) -> None:
|
|
pass
|
|
|
|
def onOverlayStateChanged(self, packageName: str, newState: int) -> None:
|
|
pass
|
|
|
|
def isUpgradePending(self, packageName: str) -> bool:
|
|
return False
|
|
|
|
def getCategoryForOverlay(self, packageName: str) -> Optional[str]:
|
|
with self._lock:
|
|
info = self._store.getOverlay(packageName)
|
|
return info.getCategory() if info else None
|
|
|
|
def getPriority(self, packageName: str) -> int:
|
|
with self._lock:
|
|
info = self._store.getOverlay(packageName)
|
|
return info.getPriority() if info else 0
|
|
|
|
def toString(self) -> str:
|
|
with self._lock:
|
|
return (
|
|
f"OverlayManager(overlays={self._store.getOverlayCount()}, "
|
|
f"transactions={len(self._transaction_history)})"
|
|
) |