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.
 

 

Logo

社区规范:仅讨论OpenHarmony相关问题。

更多推荐