feat(perception): expose active app metadata in UI tree
Tests / Test passed: 971

This commit is contained in:
2026-07-16 08:13:04 +08:00
parent 059fb272bb
commit 9a17297f1e
13 changed files with 246 additions and 17 deletions
+14
View File
@@ -5,6 +5,7 @@ from dataclasses import dataclass, field
from typing import Any
from core.errors import DeviceOfflineError, DriverError
from core.models import ActiveApp
from driver.base import Driver
# Android KeyEvent.KEYCODE_HOME. Kept as a literal rather than importing the
@@ -170,6 +171,19 @@ class AndroidDriver(Driver):
except Exception as exc:
raise DriverError("ui tree retrieval failed") from exc
def active_app(self) -> ActiveApp | None:
client = self._require_client()
try:
package = client.current_package
activity = client.current_activity
except Exception as exc:
raise DriverError("active app retrieval failed") from exc
package = package if isinstance(package, str) and package else None
activity = activity if isinstance(activity, str) and activity else None
if package is None and activity is None:
return None
return ActiveApp(platform="android", package=package, activity=activity)
def home(self) -> None:
client = self._require_client()
try:
+6 -1
View File
@@ -3,6 +3,8 @@ from __future__ import annotations
from abc import ABC, abstractmethod
from typing import Any
from core.models import ActiveApp
class Driver(ABC):
"""Driver-independent device capability interface.
@@ -71,6 +73,10 @@ class Driver(ABC):
def tree(self) -> Any:
"""Return the raw UI tree from the device driver."""
def active_app(self) -> ActiveApp | None:
"""Return foreground application metadata when the driver supports it."""
return None
@abstractmethod
def home(self) -> None:
"""Press the device home button."""
@@ -82,4 +88,3 @@ class Driver(ABC):
@abstractmethod
def unlock(self) -> None:
"""Unlock the device."""
+14
View File
@@ -4,6 +4,7 @@ from dataclasses import dataclass, field
from typing import Any
from core.errors import DeviceOfflineError, DriverError
from core.models import ActiveApp
from driver.base import Driver
@@ -161,6 +162,19 @@ class WDADriver(Driver):
except Exception as exc:
raise DriverError("ui tree retrieval failed") from exc
def active_app(self) -> ActiveApp | None:
client = self._require_client()
try:
response = client.execute_script("mobile: activeAppInfo")
except Exception as exc:
raise DriverError("active app retrieval failed") from exc
if not isinstance(response, dict):
return None
bundle_id = response.get("bundleId")
if not isinstance(bundle_id, str) or not bundle_id:
return None
return ActiveApp(platform="ios", bundle_id=bundle_id)
def home(self) -> None:
client = self._require_client()
try: