""" Android app.slice 组件 — Slice, SliceManager, SliceProvider, SliceSpec 等 方法签名完全对齐 Android SDK """ from __future__ import annotations import uuid from typing import Any, Dict, List, Optional, Set from .._core import Stub, AndroidOnlyError from ..java.lang import RuntimeException IllegalArgumentException = type("IllegalArgumentException", (RuntimeException,), {}) # ═══════════════════════════════════════════════════════════════ # SliceSpec # ═══════════════════════════════════════════════════════════════ class SliceSpec(Stub): """SliceSpec — Slice 规范""" def __init__(self, type_: str, revision: int = 1): super().__init__() self._type = type_ self._revision = revision def getType(self) -> str: return self._type def getRevision(self) -> int: return self._revision def toString(self) -> str: return f"SliceSpec{{type={self._type}, revision={self._revision}}}" def hashCode(self) -> int: return hash((self._type, self._revision)) & 0x7FFFFFFF def equals(self, other) -> bool: if not isinstance(other, SliceSpec): return False return self._type == other._type and self._revision == other._revision # ═══════════════════════════════════════════════════════════════ # SliceItem # ═══════════════════════════════════════════════════════════════ class SliceItem(Stub): """SliceItem — Slice 数据项""" FORMAT_TEXT = "text" FORMAT_IMAGE = "image" FORMAT_ACTION = "action" FORMAT_INT = "int" FORMAT_LONG = "long" FORMAT_REMOTE_INPUT = "remote_input" FORMAT_SLICE = "slice" def __init__(self, format_: str, hints: List[str], sub_type: str = ""): super().__init__() self._format = format_ self._hints = list(hints) self._sub_type = sub_type self._text: Optional[str] = None self._icon: Any = None self._intent: Any = None self._slice: Optional["Slice"] = None self._remote_input: Any = None self._action: Any = None self._color: int = 0 def getFormat(self) -> str: return self._format def getHints(self) -> List[str]: return list(self._hints) def getSubType(self) -> str: return self._sub_type def getText(self) -> Optional[str]: return self._text def getIcon(self) -> Any: return self._icon def getIntent(self) -> Any: return self._intent def getSlice(self) -> Optional["Slice"]: return self._slice def getRemoteInput(self) -> Any: return self._remote_input def getAction(self) -> Any: return self._action def getColor(self) -> int: return self._color def toString(self) -> str: return f"SliceItem{{format={self._format}, hints={self._hints}}}" # ═══════════════════════════════════════════════════════════════ # Slice # ═══════════════════════════════════════════════════════════════ class Slice(Stub): """Slice — 切片数据""" HINT_TITLE = "title" HINT_SUBTITLE = "subtitle" HINT_SUMMARY = "summary" HINT_KEYWORDS = "keywords" HINT_TTL = "ttl" HINT_LAST_UPDATED = "last_updated" HINT_PERMISSION = "permission" HINT_SHORTCUT = "shortcut" HINT_TOGGLE = "toggle" HINT_SLIDER = "slider" HINT_TINT = "tint" HINT_LIST = "list" HINT_GRID = "grid" HINT_VERTICAL = "vertical" HINT_HORIZONTAL = "horizontal" HINT_PARTIAL = "partial" HINT_SEE_MORE = "see_more" HINT_NO_TINT = "no_tint" HINT_SHOW_BACKGROUND = "show_background" HINT_LARGE = "large" HINT_ERROR = "error" def __init__(self, uri: str = "", hints: Optional[List[str]] = None, spec: Optional[SliceSpec] = None): super().__init__() self._uri = uri self._hints = hints or [] self._items: List[SliceItem] = [] self._spec = spec or SliceSpec("default") self._calling_uid: int = -1 self._calling_package: Optional[str] = None def getUri(self) -> str: return self._uri def getHints(self) -> List[str]: return list(self._hints) def getItems(self) -> List[SliceItem]: return list(self._items) def getSpec(self) -> SliceSpec: return self._spec def getCallingUid(self) -> int: return self._calling_uid def getCallingPackage(self) -> Optional[str]: return self._calling_package def getItem(self, format_: str) -> Optional[SliceItem]: for item in self._items: if item.getFormat() == format_: return item return None def toString(self) -> str: return f"Slice{{uri={self._uri}, hints={self._hints}}}" class Builder(Stub): """Slice.Builder — 构建器""" def __init__(self, uri: str, spec: SliceSpec): super().__init__() self._uri = uri self._spec = spec self._hints: List[str] = [] self._items: List[SliceItem] = [] self._caller_needed: bool = False def setCallerNeeded(self, needed: bool) -> "Slice.Builder": self._caller_needed = needed return self def addHints(self, hints: List[str]) -> "Slice.Builder": self._hints.extend(hints) return self def addSubSlice(self, sub_slice: Slice, hints: List[str]) -> "Slice.Builder": item = SliceItem(SliceItem.FORMAT_SLICE, hints) item._slice = sub_slice self._items.append(item) return self def addIcon(self, icon: Any, hints: List[str], sub_type: str = "") -> "Slice.Builder": item = SliceItem(SliceItem.FORMAT_IMAGE, hints, sub_type) item._icon = icon self._items.append(item) return self def addText(self, text: str, hints: List[str], sub_type: str = "") -> "Slice.Builder": item = SliceItem(SliceItem.FORMAT_TEXT, hints, sub_type) item._text = text self._items.append(item) return self def addAction(self, action: Any, hints: List[str], sub_type: str = "") -> "Slice.Builder": item = SliceItem(SliceItem.FORMAT_ACTION, hints, sub_type) item._action = action self._items.append(item) return self def addInt(self, value: int, hints: List[str], sub_type: str = "") -> "Slice.Builder": item = SliceItem(SliceItem.FORMAT_INT, hints, sub_type) item._text = str(value) self._items.append(item) return self def addLong(self, value: int, hints: List[str], sub_type: str = "") -> "Slice.Builder": item = SliceItem(SliceItem.FORMAT_LONG, hints, sub_type) item._text = str(value) self._items.append(item) return self def addRemoteInput(self, remote_input: Any, hints: List[str], sub_type: str = "") -> "Slice.Builder": item = SliceItem(SliceItem.FORMAT_REMOTE_INPUT, hints, sub_type) item._remote_input = remote_input self._items.append(item) return self def build(self) -> "Slice": s = Slice(self._uri, self._hints, self._spec) s._items = list(self._items) return s # ═══════════════════════════════════════════════════════════════ # ListBuilder # ═══════════════════════════════════════════════════════════════ class ListBuilder(Stub): """ListBuilder — Slice 列表构建器""" def __init__(self, uri: str, spec: SliceSpec): super().__init__() self._uri = uri self._spec = spec self._header_slice: Optional[Slice] = None self._rows: List[Slice] = [] self._grid_rows: List[Slice] = [] self._input_ranges: List[Slice] = [] self._sliders: List[Slice] = [] self._ranges: List[Slice] = [] self._select_toggles: List[Slice] = [] def setHeader(self, slice_: Slice) -> "ListBuilder": self._header_slice = slice_ return self def addRow(self, slice_: Slice) -> "ListBuilder": self._rows.append(slice_) return self def addGridRow(self, slice_: Slice) -> "ListBuilder": self._grid_rows.append(slice_) return self def addInputRange(self, slice_: Slice) -> "ListBuilder": self._input_ranges.append(slice_) return self def addSlider(self, slice_: Slice) -> "ListBuilder": self._sliders.append(slice_) return self def addRange(self, slice_: Slice) -> "ListBuilder": self._ranges.append(slice_) return self def addSelectToggle(self, slice_: Slice) -> "ListBuilder": self._select_toggles.append(slice_) return self def build(self) -> Slice: return Slice(self._uri, ["list"], self._spec) def toString(self) -> str: return f"ListBuilder{{uri={self._uri}}}" # ═══════════════════════════════════════════════════════════════ # SliceManager # ═══════════════════════════════════════════════════════════════ class SliceManager(Stub): """SliceManager — Slice 管理器""" def __init__(self): super().__init__() self._pinned_slices: Dict[str, Slice] = {} self._permissions: Dict[str, Set[str]] = {} def bindSlice(self, uri: str, specs: Set[SliceSpec]) -> Optional[Slice]: return self._pinned_slices.get(uri) def bindSliceForIntent(self, intent: Any, specs: Set[SliceSpec]) -> Optional[Slice]: return None def mapIntentToUri(self, intent: Any) -> Optional[str]: return None def grantSlicePermission(self, toPackage: str, uri: str): if uri not in self._permissions: self._permissions[uri] = set() self._permissions[uri].add(toPackage) def revokeSlicePermission(self, toPackage: str, uri: str): if uri in self._permissions: self._permissions[uri].discard(toPackage) def checkSlicePermission(self, uri: str, pid: int, uid: int) -> int: return 0 # PERMISSION_GRANTED def pinSlice(self, uri: str, specs: Set[SliceSpec]) -> Optional[Slice]: slice_ = self._pinned_slices.get(uri) if slice_: return slice_ s = Slice(uri, spec=list(specs)[0] if specs else None) self._pinned_slices[uri] = s return s def unpinSlice(self, uri: str): self._pinned_slices.pop(uri, None) def getPinnedSlices(self) -> List[Slice]: return list(self._pinned_slices.values()) def getSliceDescendants(self, uri: str) -> List[str]: return [] def getSlice(self, uri: str) -> Optional[Slice]: return self._pinned_slices.get(uri) def getAllowedPackages(self) -> List[str]: return [] def slicePinUser(self, uri: str) -> int: return 0 def getPinnedSliceSpecs(self, uri: str) -> Set[SliceSpec]: return set() def toString(self) -> str: return f"SliceManager@{hex(id(self))}" # ═══════════════════════════════════════════════════════════════ # SliceProvider # ═══════════════════════════════════════════════════════════════ class SliceProvider(Stub): """SliceProvider — Slice 提供者""" def __init__(self): super().__init__() def onCreateSliceProvider(self) -> bool: return True def onBindSlice(self, sliceUri: str, specs: Set[SliceSpec]) -> Optional[Slice]: return None def onSlicePinned(self, sliceUri: str): pass def onSliceUnpinned(self, sliceUri: str): pass def onMapIntentToUri(self, intent: Any) -> Optional[str]: return None def handleSliceRequest(self, uri: str, specs: Set[SliceSpec]) -> Optional[Slice]: return self.onBindSlice(uri, specs) def getCallingPackage(self) -> Optional[str]: return None def toString(self) -> str: return f"SliceProvider@{hex(id(self))}" # ═══════════════════════════════════════════════════════════════ # __all__ # ═══════════════════════════════════════════════════════════════ __all__ = [ "Slice", "SliceManager", "SliceProvider", "SliceSpec", "SliceItem", "ListBuilder", ]