cast+流程清单

源码根:foundation/CastEngine/castengine_cast_framework/,以下函数与行号均已在本机 6.1 LTS 源码逐一核实。

0. 先建立整体心智模型

一次 Cast+ 投屏 = 两条通道 + 六个阶段

通道建立方软总线 API用途
控制/协商通道 CastPlusSessionNameSink(SessionServer::CreateListenSocketSocket/Bind/Listen设备咨询、会话协商数据
数据握手通道 com.huawei.android.airsharing+CastPlusDiscoveryModuleSink(SinkSessionRcvServerSession 会话握手 JSON → DM 认证

六个阶段:① Sink 服务启动 → ② 发现(Sink 发布)→ ③ Source 连接+协商 → ④ Sink 握手认证(DM)→ ⑤ 会话建立+RTSP M1-M4 → ⑥ 媒体播放(Mirror/Stream)

关键分工:认证完全交给 DM(CastEngine 只注册回调消费结果),组网由 DM 内部完成,CastEngine 自己只管两条业务通道。


阶段一:Sink 服务启动

入口 REGISTER_SYSTEM_ABILITY_BY_ID(CastSessionManagerService, CAST_ENGINE_SA_ID, false)cast_session_manager_service.cpp:69),进程启动后走 OnStart()(:256):

OnStart()
 ├─ Publish()                                  // 发布 SA
 ├─ SinkSessionRcvServer::CreateSinkSessionListener()   // :270 数据握手通道
 │    └─ CreateSessionServer(pkgName=devicemanager,
 │         "com.huawei.android.airsharing+CastPlusDiscoveryModule")   // 软总线会话
 ├─ SessionServer::CreateListenSocket()        // :278 控制通道,50ms×1200 次重试
 │    └─ Socket("CastPlusSessionName") → Listen(socketId, qos, 3, &listener)
 ├─ RegisterCollaborationListen()
 └─ RegisterSinkAuthCallback()                 // :320
      └─ DeviceManager::RegisterSinkBindCallback(PKG_NAME, CastSinkAuthCallback)

控制通道 listener 的 4 个回调(:135-179)是后续所有协商逻辑的入口:

  • OnBind → OnConsultSessionOpened(Source 连上来了)
  • OnBytes → ConnectionManager::OnConsultDataReceived(Source 发来协商数据)
  • OnNegotiate2 → ConnectionManager::OnNegotiate2ACL 鉴权钩子,软总线在建连时回调)
  • OnShutdown → CancelStartProjectionClientAbility

排查要点:日志出现 Create session server SUCCESSFULLY. 说明控制通道监听成功,否则 Source 永远连不上。


阶段二:Sink 打开"可发现"开关

用户在大屏打开投屏开关 → SetDiscoverable(true)(:943):

SetDiscoverable(enable)
 ├─ WifiDisplayManager::StartListen()
 ├─ ConnectionManager::EnableDiscoverable()
 └─ DiscoveryManager::StartAdvertise(15, 3)    // capability=15(MIRROR|STREAM|COOPERATION|HICAR), medium=3(BLE|COAP)
      └─ DeviceManager::StartAdvertising(advertiseParam, callback)
           └─ (DM 内部) PublishSoftbusLNN()     // 软总线发布 LNN

StartAdvertisediscovery_manager.cpp:232)组装 customDatacastPlus="CA60",其中 bit1=AUTH_VERSION、bit6=HMOS 标识、bit7=华为标识。Source 侧解析这段数据判断对端能力(discovery_manager.cpp:442 有对称的解析逻辑)。


阶段三:Source 发起连接与协商(重点分支多)

Source 手机点击大屏后,软总线 Socket 连到 CastPlusSessionName,触发 Sink 侧回调链:

Sink: OnNegotiate2 (cast_session_manager_service.cpp:176)

Source 侧对称逻辑 OnConsultDataReceivedFromSink(:505)→ handleConsultData(:543)按 Sink 回传结果分支:AUTH_SUCCESS_FROM_SINK→正常进入下一步;CONNECTION_FAILED→断连并打点 S8_CONSULT_DATA。

协商数据里的 IP/端口是加密的QueryP2PIp(:987)先通过 DM BindTarget(ACTION_QUERY_P2P_IP) 查 P2P IP,GetConsultationData(:1045)用会话密钥调 EncryptIp/EncryptPort 加密后传输。


阶段四:Sink 数据通道握手认证(ConnectionManagerSink,分支最多的环节)

Source 在数据会话(AirSharing 会话)上发握手 JSON,Sink 侧入口 ConnectionManagerSink::OnSinkDataReceivedconnection_manager_sink.cpp:65):

OnSinkDataReceived (:65)

ReplyAuthFailed(:243)内还有 PIN 重试分支:IncreasePinRetryCnt()(:281)超阈值则直接失败。DM 内部的具体认证状态机(PIN 弹窗、v2 凭据认证)在 DM 模块,可配合 openharmony-dm-auth skill 看。


阶段五:会话建立——状态机 + 连接四步

5.1 状态机(include/cast_session_common.h:32 + cast_session_state.cpp

状态:DEFAULT → DISCONNECTED → CONNECTING → CONNECTED → PLAYING,旁路 PAUSED / AUTHING / DISCONNECTING / MIRROR_TO_STREAM / STREAM_TO_MIRROR 等。

实现是经典的 State 模式(每个状态一个类,Enter() + HandleMessage(msg)),消息驱动迁移(cast_session_state.cpp):

DefaultState      --收设备 ready--> DisconnectedState
DisconnectedState --MSG_START_AUTH--> AuthingState     (启动 MSG_CONNECT_TIMEOUT 定时器)
                  --MSG_CONNECT-----> ConnectingState
AuthingState      --MSG_CONNECT-----> ConnectingState   (认证成功回调触发)
ConnectingState   --MSG_SETUP------> 触发 ProcessSetUp
ConnectedState    --MSG_PLAY-------> PlayingState
ConnectedState    --MSG_PAUSE------> PausedState
任意状态          --MSG_DISCONNECT/ERROR/超时--> DisconnectingState → DisconnectedState

超时保护:进入 Authing/Connecting 都 SendCastMessageDelayed(MSG_CONNECT_TIMEOUT, TIMEOUT_CONNECT),迁移时 RemoveMessage 取消。

5.2 连接四步(cast_session_impl.cpp

AddDevice (:307) → 状态机进 Authing → ProcessAuth (:1084) // 6.1 LTS 中实际由 DM 认证链路驱动


阶段六:RTSP M1-M4 能力协商

RTSP 报文入口 RtspController::OnRequestrtsp_controller.cpp:194),用函数表 requestFuncMap_ 按方法名分发(:1527-1535):

消息方法处理函数行号作用
M1OPTIONSProcessOptionRequest:407能力询问,回响应后发 SendOptionM1M2waitRsp_=WAITING_RSP_OPT_M2
M2ANNOUNCEProcessAnnounceRequest/DealAnnounceRequest:349/:292Source 宣告属性(分辨率、音视频格式、UIBC 能力)
M3GET_PARAMETERProcessGetParameterRequestM3:447取参数集
M4SET_PARAMETERProcessSetParamRequestM4:651设定会话参数、加密算法
SETUPProcessSetupRequest:431→ listener_->OnSetup → ProcessSetUp
PLAYProcessPlayRequest:501→ listener_->OnPlay → ProcessPlay
PAUSE/TEARDOWNProcessPauseRequest/ProcessTearDownRequest:534/:558暂停/拆会话
RENDER_READYProcessRenderReadyRequest:585对端渲染就绪
事件通道ProcessEventChangeRequest:479Mirror↔Stream 切换、反控事件都走这里 → NotifyEventChange
TriggerProcessGetTrigger:461触发类事件

保活:OnTimeKeepAlive(:318)→ RtspChannelManager::ScheduleKeepAlive(:239),KeepAlive 间隔通过 SET_PARAMETER 协商。


阶段七:Mirror 镜像媒体链路(Source 推流 → Sink 解码上屏)

Source 端:VirtualDisplay(虚拟屏录屏采集)→ VideoEncoder(H264/H265 编码)→ RtpPackager(RTP 封包)→ send_queue → 软总线通道。

Sink 端接收解码链路(session/src/mirror/src/):

rtp_depackager.cpp DoRtpDepackagerParamCheck (:44) // 校验 RTP 版本、payloadType(AVC=视频/AAC=音频)

排查口诀video first frame. 是"投屏上屏成功"的硬指标;earlyUs 为正偏大=音频落后(丢音频),为负偏大=视频落后(丢视频)。


阶段八:反控(UIBC)与 Mirror↔Stream 切换

反控remote_control_sink.cpp):Sink 捕获遥控器/键鼠事件 → OnInputEvent(:138)→ ConstructRemoteCtrlPacket(坐标映射基于 UpdateVideoSize/UpdateWindowSize 更新的 video/屏幕尺寸)→ SendPacket 发给 Source → Source 侧 depacketizer 解析解密 → 注入全局输入。M2/M3 协商里的 genericList 能力决定是否支持。

Mirror↔Stream 自动切换cast_session_impl.cpp):Source 检测到影音播放 → 发事件通道报文 → ProcessMirrorToStream(:1418)= PauseMirrorForStream + SendEventChange(MIRROR_TO_STREAM),Sink 转 CastStreamPlayer 拉流播放(Source 可熄屏);播放结束 → ProcessStreamToMirror(:1435)切回。日志特征:Transfer to MIRROR_TO_STREAM

完整时序(正常投屏一次):

Sink 启动 → 两条通道监听 → SetDiscoverable(true) → PublishSoftbusLNN
Source 发现 → DM 组网 + PIN 认证 → Socket 连 CastPlusSessionName
Sink OnNegotiate2(ACL) → OnBind → OnConsultSessionOpened
Source 发协商数据 → OnConsultDataReceived → Source 创建会话
数据通道握手 → DM BindTarget 认证 → AUTH_FINISH → 握手回复
RTSP: M1→M2→M3→M4 → SETUP(建通道) → PLAY(起播)
Sink "video first frame." → 上屏 → 反控/切换事件 → TEARDOWN 结束

建议的源码阅读顺序

  1. cast_session_manager_service.cpp:OnStart / SetDiscoverable / CreateCastSession / CastSinkAuthCallback
  2. device_manager/src/discovery_manager.cpp:StartAdvertise 参数组装
  3. device_manager/src/connection_manager.cpp + connection_manager_sink.cpp:所有分支逻辑(状态分支最值得精读)
  4. session/src/cast_session_state.cpp:状态机骨架 → cast_session_impl.cpp 四步
  5. session/src/rtsp/src/rtsp_controller.cpp:报文分发
  6. session/src/mirror/src/video/:解码与音画同步
  7. session/src/stream/:Stream 模式(CastStreamPlayer)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值