openharmony我看那个关系图有些昏头,结合自己的理解做了这个链路图,分为从app发起向下传递和底层回调向上传递的关系流程图方便理解:

app向下传递:

应用App(ArkTS)
        ↓ IPC
DeviceManagerService 主服务
        ├─ AdvertiseManager → SoftbusListener → DSoftBus(C底层) → WiFi/蓝牙广播本机
        └─ DiscoveryManager → SoftbusListener → DSoftBus(C底层) → 扫描周边设备
PinHolder:仅配对时被调用,不直接访问软总线
App (ArkTS) → IPC → DeviceManagerService → DiscoveryManager → SoftbusListener → DSoftBus 底层 → BLE/WiFi 扫描

底层回调向上传递:
 

WiFi/蓝牙硬件有新设备/设备离线
        ↓
DSoftBus(C底层裸指针回调)
        ↓(唯一出口:SoftbusListener)
SoftbusListener(底层事件统一入口)
        ├─ 广播事件 → AdvertiseManager
        └─ 发现/上下线事件 → DiscoveryManager
                ↓
DiscoveryManager → DeviceManagerServiceListener(上层业务回调)
                        ↓ IPC
App 收到 onDeviceFound / deviceOnline 事件

设备配对PIN校验流程:
App发起配对 → PinHolder校验PIN → DeviceManagerServiceListener → App收到配对结果
BLE/WiFi → DSoftBus C 回调 → SoftbusListener → DiscoveryManager → DeviceManagerServiceListener → IPC → App 收到 onDeviceFound

pin配对流程:

App 发起 bind → DeviceManagerService → PinHolder 校验 PIN → DeviceManagerServiceListener → App 接收配对结果

像AdvertiseManager、DiscoveryManager 这些管理器全部属于devicemanager

App(ArkTS)
    ↓ IPC
┌─────────────────────────────────────┐
│ DeviceManagerService(顶层容器SA)    │
│  内部持有全部对象:                   │
│ softbusListener_、listener_、三大Mgr │
└───────────┬──────────────────┬───────┘
            │                  │
            ▼                  ▼
    SoftbusListener     DeviceManagerServiceListener
        ↙️        ↘️               ↓
AdvertiseManager DiscoveryManager PinHolder
        │            │
        └────┬───────┘
             ▼
      DSoftBus 分布式软总线底层(独立SA,纯C通信基座)
             ↓
        WiFi/BLE硬件链路

整体框架:

┌─────────────────────────────┐
│ 应用层 App(ArkTS/NAPI)       │
│ 调用接口:startDiscover、publishDevice、bindDevice 等
└───────────────┬─────────────┘
                │ IPC跨进程通信
                ▼
┌─────────────────────────────────────────────────────────────┐
│ 设备管理服务 DeviceManagerService(独立SA)                    │
│  内部组件:                                                  │
│  ├─ DeviceManagerServiceListener(上层事件分发监听)          │
│  ├─ SoftbusListener(软总线适配桥接监听)                     │
│  ├─ AdvertiseManager 广播管理器                              │
│  ├─ DiscoveryManager 发现扫描管理器                           │
│  └─ PinHolder PIN配对管理器                                  │
└───────────────┬─────────────────────────────────────────────┘
                │ SoftbusListener 调用软总线C接口
                ▼
┌─────────────────────────────┐
│ 底层 DSoftBus 分布式软总线SA  │
│ 纯C实现:设备扫描、广播、组网、链路管理
└───────────────┬─────────────┘
                │
                ▼
        WiFi / BLE / BR蓝牙 物理通信链路

看懂了具体的框架结构,再来看具体的流程代码就好理解了

开机启动

开机启动,初始化最底层的软总线分布式系统(SA1)和上一层DM(SA2)的对象,SA2的对象是直接初始化,不管SA1有没有初始化完成,等SA1初始化完成以后,将SA2注册到SAMGR(SAmanager),触发回调函数OnAddSystemAbility,创建底层桥接对象softbuslistener,这个softbuslistener是软总线SA2暴露的唯一桥接接口。

void IpcServerStub::OnStart()
{
    // 1. 先初始化上层Listener、三大Manager(你代码里的InitDMServiceListener)
    DeviceManagerService::GetInstance().InitDMServiceListener();
    // 2. 向SAMGR注册监听:等待软总线SA启动完成
    AddSystemAbilityListener(SOFTBUS_SERVER_SA_ID);
}

// 软总线SA启动后,SAMGR回调这个函数
void IpcServerStub::OnAddSystemAbility(int32_t systemAbilityId, const std::string& deviceId)
{
    if (systemAbilityId == SOFTBUS_SERVER_SA_ID) {
        // 3. 软总线就绪后,才创建softbusListener_
        DeviceManagerService::GetInstance().InitSoftbusListener();
    }
}
【系统开机init】
        ↓ 并行拉起
┌──────────────┐               ┌─────────────────────┐
│ softbus_server SA │         │ device_manager SA    │
│ (DSoftBus底层)  │         │ OnStart 立刻执行     │
└────────┬───────┘               └──────────┬────────┘
         │                                    │
         │ 软总线完成初始化、注册到SAMGR        │ InitDMServiceListener()
         │                                    │ 创建listener_、三大Manager
         ▼                                    │ 注册监听SOFTBUS_SERVER_SA_ID
SAMGR系统能力管理器 ◄──────────────────────────┘
         │
         │ 回调 OnAddSystemAbility(SOFTBUS_SERVER_SA_ID)
         ▼
device_manager SA 执行 InitSoftbusListener()
         ↓
softbusListener_ 对象创建完成,链路打通
         ↓
App → IPC → DeviceManagerService → 三大Manager → softbusListener → DSoftBus → 蓝牙/WiFi

内部变量初始化

int32_t DeviceManagerService::InitSoftbusListener()
{
    softbusListener_ = std::make_shared<SoftbusListener>();
    return DM_OK;
}
int32_t DeviceManagerService::InitDMServiceListener()
{
    listener_ = std::make_shared<DeviceManagerServiceListener>();
    advertiseMgr_ = std::make_shared<AdvertiseManager>(softbusListener_);
    discoveryMgr_ = std::make_shared<DiscoveryManager>(softbusListener_, listener_);
    pinHolder_ = std::make_shared<PinHolder>(listener_);
    return DM_OK;
}
  • AdvertiseManager:只需要底层桥接,仅持有 softbusListener_
  • DiscoveryManager:既要下发扫描指令给软总线,又要向上给 APP 推送设备,所以同时持有 softbusListener_ + listener_
  • PinHolder:完全不碰软总线,只处理上层配对回调,只持有 listener_

注册软总线设备上下线监听,局域网内发布能力

注册全设备节点状态监听回调到软总线,RegNodeDeviceStateCb是软总线的原生C接口,

  • 参数:
    • DM_PKG_NAME:device_manager 模块包名,区分不同业务模块注册的回调;
    • softbusNodeStateCb_:静态 C 风格回调函数,软总线底层有设备上线 / 下线 / 信息变更时触发;
  • 回调内部会转发到 OnSoftbusDeviceOnline/Offline/InfoChanged 三个成员函数。
  • 注册节点状态好后执行InitSoftPublishLNN初始化本机广播发布能力
int32_t SoftbusListener::InitSoftbusListener()
{   
    // softbus 注册软总线节点状态事件回调
    RegNodeDeviceStateCb(DM_PKG_NAME, &softbusNodeStateCb_);
    return InitSoftPublishLNN();
}

int32_t SoftbusListener::InitSoftPublishLNN()
{
    int32_t ret;
    PublishInfo publishInfo;
    // 广播标识:绑定DM服务SA ID,区分不同业务广播
    publishInfo.publishId = DISTRIBUTED_HARDWARE_DEVICEMANAGER_SA_ID;
    // 主动广播模式:持续对外发送广播包
    publishInfo.mode = DiscoverMode::DISCOVER_MODE_ACTIVE;
    // 自动介质:自动使用BLE/WiFi多链路广播
    publishInfo.medium = ExchangeMedium::AUTO;
    // 高频广播:设备发现灵敏度高,适合硬件设备发现场景
    publishInfo.freq = ExchangeFreq::HIGH;
    // 广播携带能力标识:OSD分布式硬件设备能力
    publishInfo.capability = DM_CAPABILITY_OSD;
    // 不开启测距
    publishInfo.ranging = false;

    // 读取系统参数:是否允许设备被发现
    char discoverStatus[DISCOVER_STATUS_LEN + 1] = {0};
    GetParameter(DISCOVER_STATUS_KEY, "not exist", discoverStatus, DISCOVER_STATUS_LEN);

    // 核心软总线接口:启动本机广播
    ret = PublishLNN(DM_PKG_NAME, &publishInfo, &softbusPublishCallback_);
    // 标记全局广播状态:本机允许被其他设备发现
    g_publishStatus = PulishStatus::ALLOW_BE_DISCOVERY;
    // 监听系统开关参数变化,用户关闭设备可见时动态停广播
    ret = WatchParameter(DISCOVER_STATUS_KEY, &OnParameterChgCallback, nullptr);
    return ret;
}

模块调用InitDeviceManager方法进行初始化例子

以NAPI模块为例子,NAPI模块是负责将SA2的接口打包暴露给JS调用,应用层就可以使用暴露的这个接口实现相关的功能,传入模块的包名和回调函数,DM内部会记录这个包名,后续调用广播、扫描、设备事件全部以此为标识。


int32_t AccessManager::InitDeviceManager()
{
    // DH_FWK_PKG_NAME ohos.dhardware
    return DeviceManager::GetInstance().InitDeviceManager(DH_FWK_PKG_NAME, shared_from_this());
}

完整链路图

ArkTS应用代码
        ↓ createDeviceManager(bundleName)
NAPI层 DeviceManagerNapi::CreateDeviceManager
        ↓ 调用全局单例
DeviceManager::GetInstance()
        ↓ 执行对外初始化入口
DeviceManagerImpl::InitDeviceManager(bundleName, 回调)
        ↓
DM内部保存该bundleName上下文,完成注册,允许使用设备发现/广播/配对能力
        ↓
App后续调用startDiscover(),DM根据bundleName区分任务,底层软总线扫描设备
        ↓
软总线上报设备事件 → DM按bundleName分发回调 → NAPI层转发给ArkTS

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐