网络HDC截屏
OpenHarmony 4.0 网络HDC 通过snapshot_display命令截屏遇到问题(截屏在使用网络 HDC 失败、但用 USB HDC 正常):
11-06 11:12:15.023 540 877 I C02f01/ATMProxy: [GetNativeTokenInfo]:result from server data = 0
11-06 11:12:15.024 21205 21205 W C04201/DisplayManagerProxy: <297>GetDisplaySnapshot: DisplayManagerProxy::GetDisplaySnapshot SendRequest nullptr.
11-06 11:12:15.024 21205 21205 E C04201/DisplayManager: <473>GetScreenshot: DisplayManager::GetScreenshot failed!
11-06 11:12:15.027 21205 21205 W C01510/IPCObjectStub: 68: destroy, desc: ohos.rosen.RSIApplicationAgent
11-06 11:12:15.035 21205 21205 W C01510/ProcessSkeleton: 51: destroy
从日志表明 网络 HDC(hdc over TCP)连接时,DisplayManager 的 binder 调用失败,
IPC 没有建立到系统服务(DisplayManagerService),导致 SendRequest 返回空
1. 问题根因分析
USB HDC 正常的原因
USB 模式下,HDC daemon(hdcd)默认运行在 系统 UID(root 或 system) 下,有 ohos.permission.CAPTURE_SCREEN 等权限。
当执行:hdc shell snapshot_display 时,
hdcd 调用 DisplayManager::GetScreenshot() → DisplayManagerService → SurfaceFlinger,
权限校验通过,返回截图数据。
网络 HDC 失败的原因
当你用 网络连接 (hdc -t tcp connect) 时:
hdcd 服务端进程在设备上仍旧是 hdcd,但客户端(PC侧)没有 USB 权限校验链;
网络 HDC 通常走 非 root 认证通道(相当于 shell 用户),此时:
1. binder 无法建立 IPC 通信(SendRequest nullptr);
2. 或者 DisplayManagerService 拒绝请求(权限不足);
3. 所以上层 GetDisplaySnapshot() 返回空指针。
二、日志关键点说明
W DisplayManagerProxy: SendRequest nullptr.
E DisplayManager: GetScreenshot failed!
意味着:
> 代理端 IpcProxy 没有拿到对应的系统服务;
> 一般发生于:
- binder token 不存在
- 当前进程用户不是 system/root
- DisplayManagerService 未暴露接口给普通应用/进程
三、验证思路
1. 查看当前执行命令的进程身份
在网络 HDC 下运行:
hdc shell
id
ps -ef | grep hdcd
检查输出是否为:uid=2000(shell) gid=2000(shell)
如果不是 root/system,而是 shell 用户,则没有权限调用截图。
2. 验证 binder 是否注册成功
在设备上执行:
hidumper -s ability
hidumper -s display
或者:
cat /dev/binderfs/binder_logs
如果看不到 DisplayManagerService 注册的 binder 句柄,说明网络 hdc 下无法访问系统 SA。
四、解决方案 / 变通方法
方案1:用 root 权限运行 hdc 网络会话
如果设备允许:
hdc tconn <device_ip>
hdc shell
su
snapshot_display
如果 su 命令不可用,可在 hdcd 启动参数中强制以 root 运行(需设备端修改)。
方案2:修改 display_manager_service 的访问策略(仅限调试版)
1. 找到源码路径:foundation/graphic/display_manager/service/display_manager_service.cpp
2. 在接口注册处放宽调用权限(例如 GetDisplaySnapshot):
if (!Permission::CheckCallingPermission("ohos.permission.CAPTURE_SCREEN")) {
// 调试可暂时注释掉 return PERMISSION_DENIED
return DISPLAY_NO_PERMISSION;
}
3. 重新编译烧录后,网络 HDC 也能截屏。
正式产品禁止放宽权限,否则可能导致远程截屏漏洞。
方案3:通过 RPC 服务转发截图
如果不能改权限,可在设备端写一个小的 本地 daemon:
- 运行在 system 权限;
- 内部调用 DisplayManager::GetScreenshot();
- 提供 socket/RPC 给外部访问。
这样 hdc network 调用这个 daemon 即可拿截图。
方案4:确认 DisplayManager 是否正常注册
有时网络 hdc 连接太早,DisplayManagerService 还未注册成功。
你可以加延迟或确认 binder 注册状态后再调用:hdc shell hilog | grep "DisplayManagerService"
确认有类似日志:DisplayManagerService started successfully.
更多推荐

所有评论(0)