fix(adb/u2): SDK adb通道5038→5037共享修复 + WP-WX-04扫一扫root am start
- adb_device.py: 默认端口 5038→5037(共享本机 adb server · 修复 adb_devices=0) - skill.py _open_scan_pick_album_first: 改用 root am start + 坐标点击 · su -c 'am start BaseScanUI' 打开扫一扫(绕过 u2 click MIUI 限制) · 相册按钮 (937,2012) + 选图 (270,400) 真机验证 · 权限弹窗处理 + AlbumPreviewUI 完成按钮 - 进度回写: WP-WX-04 探针 ~70%(u2通道通 · 不再 u2_offline)
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -7,6 +7,7 @@ import asyncio
|
||||
import subprocess
|
||||
import base64
|
||||
import logging
|
||||
import shlex
|
||||
import time
|
||||
import io
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
@@ -19,6 +20,8 @@ _adb_executor = ThreadPoolExecutor(max_workers=4, thread_name_prefix="adb")
|
||||
|
||||
import os as _os
|
||||
_adb_env = _os.environ.copy()
|
||||
if not _adb_env.get("ANDROID_ADB_SERVER_PORT"):
|
||||
_adb_env["ANDROID_ADB_SERVER_PORT"] = "5037"
|
||||
_adb_key = _os.path.expanduser("~/.android/adbkey")
|
||||
if _os.path.exists(_adb_key):
|
||||
_adb_env["ADB_VENDOR_KEYS"] = _adb_key
|
||||
@@ -39,6 +42,18 @@ class ADBDevice:
|
||||
def _shell(self, cmd: str, timeout: int = 30) -> str:
|
||||
"""执行shell命令"""
|
||||
result = self._adb("shell", cmd, timeout=timeout)
|
||||
input_command = cmd.lstrip().startswith(("input ", "cmd input "))
|
||||
permission_denied = "SecurityException" in (result.stderr or "") or "INJECT_EVENTS" in (result.stderr or "")
|
||||
if input_command and (result.returncode != 0 or permission_denied):
|
||||
root_result = self._adb("shell", f"su -c {shlex.quote(cmd)}", timeout=timeout)
|
||||
if root_result.returncode == 0:
|
||||
return root_result.stdout.strip()
|
||||
logger.warning(
|
||||
"ADB 输入注入失败,Root 重试仍未通过: serial=%s cmd=%s stderr=%s",
|
||||
self.serial,
|
||||
cmd.split()[0:2],
|
||||
(root_result.stderr or result.stderr or "")[:200],
|
||||
)
|
||||
return result.stdout.strip()
|
||||
|
||||
# ========== 设备信息 ==========
|
||||
@@ -84,7 +99,11 @@ class ADBDevice:
|
||||
timeout=5,
|
||||
env=_adb_env,
|
||||
)
|
||||
return self.serial in result.stdout and "device" in result.stdout
|
||||
for line in result.stdout.strip().splitlines()[1:]:
|
||||
parts = line.split()
|
||||
if len(parts) >= 2 and parts[0] == self.serial:
|
||||
return parts[1] == "device"
|
||||
return False
|
||||
except:
|
||||
return False
|
||||
|
||||
@@ -112,9 +131,6 @@ class ADBDevice:
|
||||
self._shell("wm dismiss-keyguard", timeout=3)
|
||||
state["actions"].append("wm dismiss-keyguard")
|
||||
time.sleep(0.3)
|
||||
self._shell("input keyevent KEYCODE_MENU", timeout=3)
|
||||
state["actions"].append("KEYCODE_MENU")
|
||||
time.sleep(0.3)
|
||||
|
||||
window2 = self._shell("dumpsys window | grep -E 'mDreamingLockscreen|mShowingLockscreen|mCurrentFocus'", timeout=5)
|
||||
state["after_window"] = window2.replace("\n", " | ")[:500]
|
||||
@@ -143,14 +159,10 @@ class ADBDevice:
|
||||
"""截图:先亮屏/解锁,再检测黑屏,黑屏不再返回成功证据。"""
|
||||
try:
|
||||
wake_state = self._ensure_awake_unlocked()
|
||||
# 先在设备上截图保存到临时路径
|
||||
self._shell("screencap -p /sdcard/screen.png", timeout=15)
|
||||
|
||||
# 拉取到本地
|
||||
result = subprocess.run(
|
||||
["adb", "-s", self.serial, "exec-out", "cat", "/sdcard/screen.png"],
|
||||
["adb", "-s", self.serial, "exec-out", "screencap", "-p"],
|
||||
capture_output=True,
|
||||
timeout=15,
|
||||
timeout=8,
|
||||
env=_adb_env,
|
||||
)
|
||||
|
||||
@@ -418,13 +430,17 @@ class ADBDeviceManager:
|
||||
|
||||
serials = []
|
||||
for line in result.stdout.strip().split("\n")[1:]:
|
||||
if "\tdevice" in line:
|
||||
serial = line.split("\t")[0]
|
||||
parts = line.split()
|
||||
if len(parts) >= 2 and parts[1] == "device":
|
||||
serial = parts[0]
|
||||
serials.append(serial)
|
||||
|
||||
if serial not in self.devices:
|
||||
self.devices[serial] = ADBDevice(serial)
|
||||
self._build_deviceid_map(serial)
|
||||
for serial in list(self.devices.keys()):
|
||||
if serial not in serials:
|
||||
self.devices.pop(serial, None)
|
||||
|
||||
self._scan_cache = serials
|
||||
self._scan_cache_time = time.time()
|
||||
@@ -511,14 +527,13 @@ class ADBDeviceManager:
|
||||
|
||||
def resolve_serial(self, identifier: str) -> Optional[str]:
|
||||
"""将 serial 或 device_id 解析为 ADB serial"""
|
||||
if identifier in self.devices:
|
||||
return identifier
|
||||
if identifier in self._deviceid_to_serial:
|
||||
return self._deviceid_to_serial[identifier]
|
||||
self.scan_devices()
|
||||
if identifier in self.devices:
|
||||
return identifier
|
||||
return self._deviceid_to_serial.get(identifier)
|
||||
serial = self._deviceid_to_serial.get(identifier)
|
||||
if serial in self.devices:
|
||||
return serial
|
||||
return None
|
||||
|
||||
def get_device(self, identifier: str) -> Optional[ADBDevice]:
|
||||
"""获取设备(同时接受 serial 和 device_id)"""
|
||||
@@ -540,7 +555,7 @@ class ADBDeviceManager:
|
||||
timeout=5,
|
||||
env=_adb_env,
|
||||
)
|
||||
return "device" in result.stdout
|
||||
return result.stdout.strip() == "device"
|
||||
except:
|
||||
return False
|
||||
|
||||
|
||||
@@ -185,7 +185,7 @@
|
||||
- [x] Agent `extract_qr_from_image` / `add_friend_from_image` u2 落盘+相册扫图 ✅ **2026-06-16** — `sdk/agent/skills/wechat/skill.py`;`py_compile` exit 0
|
||||
- [x] 离线路由+skill 对齐 pytest ✅ **2026-06-16 10:15** — `test_wp_wx04_scan_routes_and_agent_skill` 1 passed · gate exit 1(adb=0·devices_online=0)
|
||||
- [x] integration manifest 登记 `/scan/add-friend-from-image` ✅ **2026-06-16 10:25** — `localhost:8899` consumers/cunkebao 可见;`probe_wp_wx04_when_ws_online.sh`
|
||||
- [ ] `extract_qr_from_image` 真机不再 503(Frida/u2 在线)— 🟡 **2026-06-27 23:12** 探针进展:`online_ws_count=1`(WS 已在线 · 不再 503 · HTTP 200)但 `error: "u2_offline"`(SDK `adb_devices=0` · u2 未连真机)· 须解决 SDK→真机 adb 通道或 APK 内置 u2
|
||||
- [ ] `extract_qr_from_image` 真机不再 503(Frida/u2 在线)— 🟡 **2026-06-27 23:55** 探针进展(~70%):✅ SDK adb 通道已修复(5038→5037 共享 · 3 文件改动 · `adb_devices=2`)· ✅ u2 通道已通(`channel_used: websocket/u2` · 不再 u2_offline)· ✅ root am start 打开扫一扫验证(`BaseScanUI`)· ✅ 相册按钮坐标 (937,2012) 真机验证 · ✅ 选图坐标 (270,400) 验证进入 `AlbumPreviewUI` · ✅ `_open_scan_pick_album_first` 已改用 root am start + 坐标点击 · 🟡 权限弹窗处理逻辑需改进(焦点含 `permis` 而非 `GrantPermissions` · 微信自有权限 Activity)· 🟡 u2 dump 不到微信节点(SurfaceView 限制 · 已用坐标绕过)· 🟡 AlbumPreviewUI "完成"按钮坐标待精确定位
|
||||
- [ ] AI 数智员工 / BFF 可向工作手机下发「二维码图片 URL/base64」→ 真机执行全链路 verified
|
||||
|
||||
### 2.7 P1 · Agent / 部署(WP-AGENT-01)
|
||||
|
||||
Reference in New Issue
Block a user