#
在这里插入图片描述
在这里插入图片描述

一、前置思考

鸿蒙"硬件互助"是超级终端的核心体验——用平板的摄像头给手机视频通话,用PC的屏幕显示手机内容,用手表的传感器给手机提供心率数据。这些能力的本质是将物理上分散的设备硬件虚拟化为一台超级设备的共享资源池

本文聚焦:

  • 分布式摄像头(distributedCamera)的调用原理与实战
  • 分布式屏幕(distributedScreen)的投射与会话管理
  • 传感器数据跨设备共享(sensor虚拟化)
  • 硬件能力抽象层(HAL)与硬件资源池化

真实痛点场景:

  1. 摄像头调用失败:明明平板就在旁边,手机上调用分布式摄像头却提示设备不可用
  2. 画面延迟大:平板摄像头画面传到手机上有明显延迟(200ms+)
  3. 资源争抢:多个应用同时请求调用同一台设备的摄像头
  4. 权限不透明:用户不知道哪些设备在访问本地硬件

二、核心原理

2.1 硬件互助架构

┌──────────────────────────────────────────────┐
│                应用层                          │
│  CameraKit / ScreenKit / SensorKit            │
├──────────────────────────────────────────────┤
│          硬件能力抽象层 (Capability HAL)       │
│  ┌────────────────────────────────────────┐  │
│  │     设备画像 (Device Profile)          │  │
│  │  {                                     │  │
│  │    deviceId: "A1B2...",               │  │
│  │    capabilities: {                     │  │
│  │      camera: { count: 2, maxRes: "4K" },│ │
│  │      screen: { size: "10.9\"", dpi: 264 },││
│  │      sensor: ["accelerometer","gyro"], │  │
│  │      audio: { speakers: 4 }            │  │
│  │    }                                   │  │
│  │  }                                     │  │
│  └────────────────────────────────────────┘  │
├──────────────────────────────────────────────┤
│       虚拟化层 (Virtualization Layer)         │
│  ├── 摄像头虚拟化 → 虚拟CameraDevice         │
│  ├── 屏幕虚拟化 → 虚拟Display                 │
│  ├── 传感器虚拟化 → 虚拟Sensor                │
│  └── 音频路由 → 虚拟AudioDevice               │
├──────────────────────────────────────────────┤
│           软总线 (DSoftBus)                    │
│   低延迟信道 (Video Stream Channel)           │
│   高带宽信道 (Screen Mirror Channel)          │
│   低功耗信道 (Sensor Data Channel)            │
└──────────────────────────────────────────────┘

2.2 分布式摄像头

调用平板或其他设备的摄像头,就如同调用本地摄像头:

import { camera } from '@kit.CameraKit';

// 枚举可用摄像头(包含分布式设备)
async function enumerateCameras(): Promise<camera.CameraDevice[]> {
  const cameraManager: camera.CameraManager = camera.getCameraManager(getContext());
  const cameras: Array<camera.CameraDevice> = cameraManager.getSupportedCameras();

  for (let i: number = 0; i < cameras.length; i++) {
    const cam: camera.CameraDevice = cameras[i];
    console.info('[Camera] ' + cam.cameraId +
      ' | 位置: ' + String(cam.cameraPosition) +  // CAMERA_POSITION_FRONT/BACK
      ' | 方向: ' + String(cam.cameraOrientation) +
      ' | 设备: ' + cam.deviceId);
    // deviceId为''表示本地,非空表示分布式设备
  }

  return cameras;
}

// 打开分布式摄像头预览
async function openDistributedCamera(cameraId: string): Promise<void> {
  const cameraManager: camera.CameraManager = camera.getCameraManager(getContext());
  const cameraInput: camera.CameraInput =
    await cameraManager.createCameraInput(cameraId);
  await cameraInput.open();

  const previewOutput: camera.PreviewOutput =
    await cameraManager.createPreviewOutput(/* surfaceId */);
  const captureSession: camera.CaptureSession =
    await cameraManager.createCaptureSession();

  captureSession.beginConfig();
  captureSession.addInput(cameraInput);
  captureSession.addOutput(previewOutput);
  await captureSession.commitConfig();
  await captureSession.start();
}

// ⚠️ 关键:分布式摄像头调用需要权限声明
// module.json5:
// {
//   "name": "ohos.permission.CAMERA",
//   "reason": "$string:camera_reason",
//   "usedScene": { "abilities": ["EntryAbility"], "when": "inuse" }
// }

2.3 分布式屏幕投射

import { display } from '@kit.ArkUI';
import { distributedScreen } from '@kit.DistributedServiceKit';

// 枚举可用分布式屏幕
async function enumerateScreens(): Promise<distributedScreen.ScreenInfo[]> {
  const screens: distributedScreen.ScreenInfo[] =
    await distributedScreen.getAvailableScreens();

  for (let i: number = 0; i < screens.length; i++) {
    const scr: distributedScreen.ScreenInfo = screens[i];
    console.info('[Screen] ' + scr.screenName +
      ' ' + scr.width + 'x' + scr.height +
      ' dpi:' + scr.densityDPI);
  }
  return screens;
}

// 建立分布式屏幕投射
async function castToScreen(targetScreenId: string): Promise<void> {
  // 创建投射会话
  const session: distributedScreen.CastSession =
    await distributedScreen.createCastSession({
      srcDisplayId: 0,           // 源显示屏ID(0=主屏)
      dstScreenId: targetScreenId
    });

  // 设置投射参数
  session.setDisplaySurface(/* surface */);
  session.setFps(60);            // 帧率
  session.setBitrate(8000000);   // 码率 8Mbps
  session.setResolution(1920, 1080);

  // 开始投射
  await session.start();

  // 监听投射状态
  session.on('stateChange', (state: distributedScreen.CastState) => {
    console.info('[Cast] 状态: ' + state);
    // CASTING / PAUSED / STOPPED / ERROR
  });
}

2.4 传感器数据共享

穿戴设备的心率传感器、血压传感器等可以共享给手机使用:

import { sensor } from '@kit.SensorServiceKit';
import { distributedSensor } from '@kit.DistributedServiceKit';

// 枚举分布式传感器
async function enumerateDistributedSensors(): Promise<distributedSensor.SensorInfo[]> {
  const sensors: distributedSensor.SensorInfo[] =
    await distributedSensor.getAvailableSensors();

  for (let i: number = 0; i < sensors.length; i++) {
    const s: distributedSensor.SensorInfo = sensors[i];
    console.info('[Sensor] 设备:' + s.deviceName +
      ' 类型:' + String(s.sensorType) +
      ' 精度:' + s.accuracy);
    // sensorType: HEART_RATE(278) / ACCELEROMETER(1) / GYROSCOPE(2)
  }
  return sensors;
}

// 订阅分布式传感器数据
async function subscribeDistributedHeartRate(sensorId: string): Promise<void> {
  sensor.on(
    sensor.SensorId.HEART_RATE,
    (data: sensor.HeartRateResponse) => {
      console.info('[HeartRate] bpm:' + data.heartRate);
    },
    { interval: 1000000000 } // 1秒采样间隔 (纳秒)
  );
}

三、硬件资源池化设计

3.1 设备能力注册

interface DeviceCapability {
  deviceId: string;
  deviceName: string;
  deviceType: number;
  capabilities: {
    camera: CameraCapability | null;
    screen: ScreenCapability | null;
    audio: AudioCapability | null;
    sensors: SensorCapability[];
    compute: ComputeCapability;
    storage: StorageCapability;
  };
  networkQuality: number;
  batteryLevel: number;
}

interface CameraCapability {
  count: number;
  maxResolution: string;     // "4K" / "1080P"
  supports4K: boolean;
  flashAvailable: boolean;
  frontCameraAvailable: boolean;
}

interface ComputeCapability {
  cpuCores: number;
  cpuFreq: number;           // GHz
  gpuModel: string;
  npuAvailable: boolean;     // AI加速芯片
  memoryGB: number;
}

3.2 能力发现与匹配

class CapabilityMatcher {
  // 查找最优摄像头设备
  static findBestCamera(
    pool: DeviceCapability[],
    requirement: { preferFront: boolean; minResolution: string }
  ): DeviceCapability | null {
    let best: DeviceCapability | null = null;
    let bestScore: number = -1;

    for (let i: number = 0; i < pool.length; i++) {
      const dev: DeviceCapability = pool[i];
      if (dev.capabilities.camera === null) continue;

      const cam: CameraCapability = dev.capabilities.camera;
      let score: number = 0;

      // 分辨率评分
      if (cam.supports4K) score += 10;
      else score += 5;

      // 前后摄像头匹配
      if (requirement.preferFront && cam.frontCameraAvailable) score += 8;

      // 网络质量评分
      score += dev.networkQuality / 10;

      if (score > bestScore) {
        bestScore = score;
        best = dev;
      }
    }
    return best;
  }

  // 查找算力设备
  static findBestCompute(pool: DeviceCapability[]): DeviceCapability | null {
    let best: DeviceCapability | null = null;
    let bestCores: number = -1;

    for (let i: number = 0; i < pool.length; i++) {
      const dev: DeviceCapability = pool[i];
      const cores: number = dev.capabilities.compute.cpuCores;
      if (cores > bestCores) {
        bestCores = cores;
        best = dev;
      }
    }
    return best;
  }
}

四、完整代码架构

Demo中的硬件互助模拟架构:

Layer 1: 设备能力注册
  ├── 摄像头 (前置/后置/4K)
  ├── 屏幕 (分辨率/DPI)
  ├── 传感器 (心率/加速度/陀螺仪)
  ├── 音频 (扬声器/麦克风)
  └── 算力 (CPU核心数/内存/NPU)

Layer 2: 能力发现
  ├── 设备画像匹配
  ├── 网络质量加权评分
  └── 最优设备推荐

Layer 3: 资源调用
  ├── 摄像头预览(模拟)
  ├── 屏幕投射(模拟)
  ├── 传感器数据流(模拟)
  └── 资源仲裁(防止争抢)

五、避坑速查

现象 原因 解决
摄像头ID变化 重启后cameraId变了 分布式设备动态分配ID 每次使用前先enumerateCameras()重新获取
Surface未释放 频繁投射内存泄漏 PreviewOutput未关闭 onDestroy中调用captureSession.release()
摄像头争抢 第二个应用打开摄像头失败 独占模式 实现资源仲裁器,排队或降级策略
投屏黑屏 投射建立成功但黑屏 surfaceId不正确 使用XComponent的surfaceId
传感器频率异常 心率数据3秒才来一次 采样间隔设置过大 降低interval为500_000_000 (0.5s)
FPS不达标 投屏帧率只有15fps 码率/分辨率设置过高 根据网络质量动态调整:优→60fps 差→30fps
设备断连未处理 摄像头画面冻结 未监听设备状态变化 注册deviceStateChange回调,断连后降级到本地
跨设备音频不同步 画面和声音延迟差很大 音视频走不同信道 启用AVSync模式,统一音视频时间戳
隐私泄露 用户不知情被调用摄像头 未提示用户 每次调用前弹出授权确认弹窗
算力设备选择错误 选了弱设备做AI推理 只看网络质量没看硬件 结合computeScore(CPU核心+NPU+Memory)综合评分

六、总结

硬件互助的核心理念是**“你的设备就是我的设备”**:

  1. 设备画像:每个设备注册自己的能力清单(摄像头/屏幕/传感器/算力)
  2. 能力匹配:根据任务需求(拍照/投屏/心率)自动选择最优设备
  3. 虚拟化调用:上层API不变——调CameraKit就行,框架自动路由到分布式设备
  4. 资源仲裁:多应用竞争同一硬件时,优先级排队或降级策略

一句话:鸿蒙硬件互助让开发者用本地API就能操作分布式硬件,框架屏蔽了网络传输、编解码、延迟优化等所有底层细节。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐