openharmony摄像头驱动到应用浏览显示 第4章 会话编排与门禁(Framework/Service)
本文为《开源鸿蒙相机:驱动到应用预览显示》系列发布版。
当前章节:第4章 会话编排与门禁(Framework/Service)
代码基线:~/work/ohos5.1/nt_backclip_vendor(基于 OpenHarmony 5.1.0 Release 移植)
发布说明:使用ai codex移植调试开源鸿蒙摄像头的任务全流程在链接https://github.com/chenlong3388/codex_fix_OpenHarmony_Camera
第4章 会话编排与门禁(Framework/Service)
本章回答的问题
- Session 是什么,为什么必须有 Session,而不是直接 open 后就 start。
- Session 有哪些关键参数和状态,这些参数/状态分别在什么位置读取和生效。
- Session 的核心机制和执行流程是什么,为什么这样设计。
- 全链路函数调用是否覆盖完整,每个函数在图里负责什么。
Session 的定义与必要性
定义(源码定义)
源码路径:foundation/multimedia/camera_framework/interfaces/inner_api/native/camera/include/session/capture_session.h
CaptureSession 是 Framework 侧“输入设备 + 输出流 + 模式参数 + 启停状态”的事务容器,核心接口是:
BeginConfigAddInputAddOutputCommitConfigStart/Stop
对应锚点:
foundation/multimedia/camera_framework/interfaces/inner_api/native/camera/include/session/capture_session.h:385-460
为什么必须有 Session
如果没有 Session,应用侧把输入输出直接逐条下发,会出现三个问题:
- 无法保证原子性:输入刚挂上、输出还没挂完就触发启动,流配置容易半成品。
- 无法保证时序合法:
Start、Commit、Begin顺序混乱时,系统无法做统一门禁。 - 无法做模式级校验:
SceneMode与profile、streamType的一致性无法集中判定。
对应源码证据:
- 状态机强制时序:
foundation/multimedia/camera_framework/services/camera_service/src/hcapture_session.cpp:1393-1432 - 提交阶段统一校验:
foundation/multimedia/camera_framework/services/camera_service/src/hcapture_session.cpp:651-700 - 启动阶段统一门禁:
foundation/multimedia/camera_framework/services/camera_service/src/hcapture_session.cpp:1063-1113
Session 关键参数(定义-读取-生效)
| 参数名 | 定义位置 | 读取位置 | 生效位置 | 参数作用 | 常见失败信号 |
|---|---|---|---|---|---|
opMode_ |
foundation/multimedia/camera_framework/services/camera_service/include/hcapture_session.h:252 |
HCaptureSession::LinkInputAndOutputs |
HStreamOperator::CreateAndCommitStreams/CommitStreams |
决定会话模式和能力门禁路径 | IsValidMode false |
isNeedCommitting_ |
foundation/multimedia/camera_framework/services/camera_service/include/hcapture_session.h:195 |
HCaptureSession::CommitConfig |
CommitConfig 分支(是否跳过重提交流) |
控制是否执行完整 Commit 流程 | 误判“已提交但未重建流” |
stateMachine_.currentState_ |
foundation/multimedia/camera_framework/services/camera_service/include/hcapture_session.h:87-90 |
CheckTransfer |
Transfer |
限定合法状态迁移 | Need to call BeginConfig... / Need to call after committing... |
isSessionStarted_ |
foundation/multimedia/camera_framework/services/camera_service/include/hcapture_session.h:254 |
Start/Stop |
Start/Stop 成功路径 |
标记运行态,用于并发会话统计 | 启动日志成功但状态未置位 |
streamType |
AddOutput 入参 |
CaptureSession::AddOutput |
HStreamOperator::StartPreviewStream 过滤 |
决定流被当作 PREVIEW/PHOTO/VIDEO | repeatStream is nullptr(需结合类型) |
settings(metadata) |
设备缓存设置 | Start/Commit |
CommitStreams/StartPreviewStream |
决定提交与启动时控制参数 | CommitStreams failed / Failed to start preview |
Session 状态机(状态是什么、干什么)
状态定义
SESSION_INIT:新建状态,只允许进入配置或释放。SESSION_CONFIG_INPROGRESS:配置中,允许继续组装输入输出。SESSION_CONFIG_COMMITTED:配置已提交,允许启动或重新配置。SESSION_STARTED:已启动,允许 stop 或重新进入配置。SESSION_RELEASED:释放态,不再参与业务流。
状态转移源码锚点:
foundation/multimedia/camera_framework/services/camera_service/src/hcapture_session.cpp:1393-1414
为什么要状态机
- 把“调用顺序错误”前置成可解释错误,而不是运行时随机失败。
- 把“配置事务”和“运行事务”分离,便于定位到底是配置失败还是启动失败。
- 支持“已启动后回到配置态”的安全重配置路径。
Session 在整体中的作用与定位
在全链路里的位置
Session 位于“能力确定之后、建流启动之前”的中枢层,既不是纯应用逻辑,也不是纯驱动逻辑,它负责把多模块能力拼装成一个可运行事务:
- 上接能力侧:消费
profile + mode + streamType(能力来源见第3章)。 - 中间编排:完成
input/output组装、状态迁移、提交门禁。 - 下接执行侧:触发
CreateStreams/CommitStreams/StartPreviewStream,把配置真正下沉到 HDI/VDI。
对应源码锚点:
- Framework 组装入口:
foundation/multimedia/camera_framework/frameworks/native/camera/src/session/capture_session.cpp:841-889 - Service 提交入口:
foundation/multimedia/camera_framework/services/camera_service/src/hcapture_session.cpp:651-700 - Service 执行入口:
foundation/multimedia/camera_framework/services/camera_service/src/hstream_operator.cpp:435-459, 1609-1666, 1088-1106, 864-912
Session 对其他功能的连接关系
| 被连接功能 | 如何连接到 Session | Session 在其中的作用 | 关键函数锚点 |
|---|---|---|---|
| 相机输入设备(CameraInput) | AddInput 把 ICameraDeviceService 绑定进会话 |
确保会话有可用输入源,否则 Commit 阶段直接阻断 | foundation/multimedia/camera_framework/services/camera_service/src/hcapture_session.cpp:540-547 |
| 预览输出(Preview) | AddOutput(PREVIEW) + StartPreviewStream |
把可显示输出纳入会话并在 Start 时拉起 | foundation/multimedia/camera_framework/frameworks/native/camera/src/session/capture_session.cpp:865-888 + foundation/multimedia/camera_framework/services/camera_service/src/hstream_operator.cpp:864-890 |
| 拍照输出(Photo) | AddOutput(PHOTO) 进入同一提交事务 |
让拍照流和预览流共享同一会话一致性检查 | foundation/multimedia/camera_framework/frameworks/native/camera/src/session/capture_session.cpp:866-868 |
| 录像输出(Video) | AddOutput(VIDEO),高帧率时触发 mode 适配 |
将 SceneMode::VIDEO 与帧率能力关联到会话模式 |
foundation/multimedia/camera_framework/frameworks/native/camera/src/session/capture_session.cpp:891-911 |
| 动图/LivePhoto | Session Commit/Start 驱动 repeat stream 扩展与启动 |
决定是否扩展 moving photo 流、何时启动 | foundation/multimedia/camera_framework/services/camera_service/src/hcapture_session.cpp:600-613, 669-672 + foundation/multimedia/camera_framework/services/camera_service/src/hstream_operator.cpp:891-910 |
| 元数据与控制参数 | Session 在 Commit/Start 传递 settings 到 StreamOperator |
把 AE/AWB 等控制元数据和流提交绑定到同一事务 | foundation/multimedia/camera_framework/services/camera_service/src/hstream_operator.cpp:1088-1095 |
| 旋转与位置语义 | Start 阶段读取 cameraPosition 并注入预览流 |
统一方向/位置语义,避免显示行为漂移 | foundation/multimedia/camera_framework/services/camera_service/src/hcapture_session.cpp:1078-1097 |
一句话定位(便于读者记忆)
Session 不是“某个单独功能”,而是“所有拍摄功能(预览/拍照/录像/动图)共享的事务总线和门禁中心”。
跨章节总链路(第4-7章)
第3章 能力注入与流桥接(HDF/HDI/VDI)
产出: mode能力表、profile能力集、stream可用边界
交付给第4章: “哪些profile在当前mode合法”
|
v
第4章 Session编排与门禁(本章)
作用: 把 input/output/mode 组织为事务并执行状态机门禁
关键输出: COMMITTED/STARTED 状态与可运行 stream 配置
|
v
第5章 输出创建与显示绑定(ArkTS/HAP)
作用: 选择 profile + 绑定 surface + 触发 createSession/start
依赖第4章: session门禁语义与失败信号解释
|
v
第6章 函数级链路走读
作用: 对第5/6章关键路径做逐函数断点与输入输出核查
回流到第4章: 验证门禁函数覆盖是否完整
为什么这样分章
- 第3章回答“能力从哪里来”。
- 第4章回答“能力怎样被组织并合法提交”。
- 第5章回答“应用如何把显示绑定真正落地”。
- 第6章回答“当链路异常时,函数级证据怎么拿”。
Session 上下游接口契约(避免章节割裂)
| 链路位置 | 上游提供给 Session 的输入 | Session 的处理动作 | Session 输出给下游 | 下游消费点 |
|---|---|---|---|---|
| 能力侧 -> Session | modeProfileMap、output profile、streamType |
CanAddOutput + ValidateOutputProfile 门禁 |
可加入会话的合法输出集合 | AddOutput 后的 streamContainer |
| 输入设备 -> Session | ICameraDeviceService |
AddInput 绑定 + ValidateSessionInputs 校验 |
有效输入设备句柄 | LinkInputAndOutputs |
| 输出对象 -> Session | IStreamCommon/IStreamRepeat |
AddOutput 挂载 + 类型化管理 |
可提交 streamInfo 列表 | CreateStreams |
| 配置参数 -> Session | settings(metadata)、opMode |
CommitConfig 汇总校验并触发提交 |
已下沉的 HDI stream 配置 | CommitStreams |
| 运行控制 -> Session | Start/Stop 调用 |
状态机迁移 + 预览启动门禁 | SESSION_STARTED/COMMITTED + 运行态流 |
StartPreviewStream / Stop |
契约破坏时的典型表现
- 能力契约破坏:
CanAddOutput check failed,说明 profile 不被 mode 接受。 - 输入契约破坏:
No inputs present,说明未完成 input 绑定。 - 输出契约破坏:
No outputs present或repeatStream is nullptr,说明输出挂载链不完整。 - 提交契约破坏:
Failed to commit config,说明 Link/Create/CommitStreams 阶段失败。 - 启动契约破坏:
Need to call after committing或Failed to start preview,说明状态或预览启动门禁失败。
全链路函数调用关系图(函数 + 作用)
模块A Framework会话创建
CameraManager::CreateCaptureSession(mode)
作用: 把SceneMode映射到OperationMode并向Service申请远端会话对象
CameraManager::CreateCaptureSessionImpl(mode, session)
作用: 按mode实例化具体Session类(Photo/Video/Portrait/通用CaptureSession)
模块B Service会话创建
HCameraService::CreateCaptureSession(session, opMode)
作用: 创建HCaptureSession并登记到captureSessionsManager_
模块C Framework配置事务
CaptureSession::BeginConfig()
作用: 打开配置窗口
CaptureSession::AddInput(input)
作用: 绑定输入设备
CaptureSession::CanAddOutput(output)
作用: 根据输出类型选profile并进入能力匹配
CaptureSession::ValidateOutputProfile(profile, outputType)
作用: 校验profile是否被当前mode支持,必要时fallback NORMAL
CaptureSession::AddOutput(output)
作用: 把输出流挂到会话,并为PREVIEW流设置API兼容版本
CaptureSession::CommitConfig()
作用: 触发服务端提交配置
模块D Service提交门禁
HCaptureSession::ValidateSessionInputs()
作用: 检查输入设备已绑定
HCaptureSession::ValidateSessionOutputs()
作用: 检查输出流已存在
HCaptureSession::ValidateSession()
作用: 聚合输入输出门禁
HCaptureSession::LinkInputAndOutputs()
作用: 验证mode并下发到StreamOperator
HCaptureSession::CommitConfig()
作用: 时序门禁+会话门禁+Link并最终状态迁移到COMMITTED
模块E Service流创建/提交
HStreamOperator::LinkInputAndOutputs(settings, opMode)
作用: 为每个流执行LinkInput并收集StreamInfo
HStreamOperator::CreateStreams(streamInfos)
作用: 向HDI创建流对象
HStreamOperator::CommitStreams(settings, opMode)
作用: 向HDI提交流配置和metadata
模块F Service启动门禁
HCaptureSession::Start()
作用: 检查状态迁移合法性,准备settings/cameraPosition并调用预览启动
HStreamOperator::StartPreviewStream(settings, cameraPosition)
作用: 仅启动RepeatStreamType::PREVIEW流
函数覆盖检查清单(本章)
| 层级 | 必经函数 | 是否覆盖 | 作用已说明 |
|---|---|---|---|
| Framework | CreateCaptureSession / BeginConfig / AddInput / CanAddOutput / ValidateOutputProfile / AddOutput / CommitConfig |
是 | 是 |
| Service Session | CreateCaptureSession / ValidateSessionInputs / ValidateSessionOutputs / ValidateSession / LinkInputAndOutputs / CommitConfig / Start |
是 | 是 |
| Service Stream | LinkInputAndOutputs / CreateStreams / CommitStreams / StartPreviewStream |
是 | 是 |
机制流程(按真实执行顺序)
| 阶段 | 关键函数 | 机制目标 | 失败后果 |
|---|---|---|---|
| 会话创建 | CameraManager::CreateCaptureSession -> HCameraService::CreateCaptureSession |
生成双端会话对象并绑定 mode | 无法进入配置阶段 |
| 配置准备 | BeginConfig + AddInput + AddOutput |
组装输入输出拓扑 | No inputs present / No outputs present |
| 能力门禁 | CanAddOutput -> ValidateOutputProfile |
保障 profile 与 mode 一致 | CanAddOutput check failed |
| 提交事务 | HCaptureSession::CommitConfig |
一次性完成校验、Link、Create/CommitStreams | Need to call BeginConfig... / Failed to commit config |
| 启动事务 | HCaptureSession::Start -> StartPreviewStream |
启动预览流进入运行态 | Need to call after committing... / Failed to start preview |
为什么这样设计(优点与取舍)
| 设计点 | 为什么这样设计 | 优点 | 代价/取舍 |
|---|---|---|---|
| 配置-提交-启动三段式 | 把构建拓扑与运行控制分离 | 错误定位粒度更清晰 | 调用链更长,阅读成本更高 |
| 状态机硬门禁 | 阻断非法时序 | 避免脏状态扩散 | 必须严格遵守调用顺序 |
ValidateOutputProfile 含 fallback |
兼容 mode 能力不完整场景 | 降低直接失败率 | 可能出现“能过门禁但显示异常”的伪成功 |
| Commit 时集中校验输入输出 | 提高事务一致性 | 提前失败,减少后续连锁错误 | 需要更多前置组装工作 |
| Start 只拉 PREVIEW 流 | 预览链路与拍照/录像链路分离 | 启动语义清晰 | 容易误判“Start success = 一定有画面” |
关键源码摘选与逐行分析
片段1:会话创建(Framework)
源码路径:foundation/multimedia/camera_framework/frameworks/native/camera/src/input/camera_manager.cpp
int32_t CameraManager::CreateCaptureSession(sptr<CaptureSession>& pCaptureSession, SceneMode mode)
{
sptr<ICaptureSession> session = nullptr;
auto serviceProxy = GetServiceProxy();
CHECK_ERROR_RETURN_RET_LOG(serviceProxy == nullptr, CameraErrorCode::INVALID_ARGUMENT,
"CreateCaptureSession(pCaptureSession) serviceProxy is nullptr");
OperationMode opMode = OperationMode::NORMAL;
if (!ConvertFwkToMetaMode(mode, opMode)) {
MEDIA_ERR_LOG("... ConvertFwkToMetaMode ... fail");
}
int32_t retCode = serviceProxy->CreateCaptureSession(session, opMode);
CHECK_ERROR_RETURN_RET_LOG(retCode != CAMERA_OK, ServiceToCameraError(retCode), "...");
captureSession = CreateCaptureSessionImpl(mode, session);
captureSession->SetMode(mode);
pCaptureSession = captureSession;
return CameraErrorCode::SUCCESS;
}
逐行分析:
- 先拿
serviceProxy,没有服务代理则不能创建会话。 SceneMode -> OperationMode做语义桥接。- 通过
serviceProxy->CreateCaptureSession申请远端ICaptureSession。 CreateCaptureSessionImpl决定具体子类(VideoSession/PhotoSession/...)。SetMode(mode)把 mode 写入本地会话对象,为后续 profile 门禁提供上下文。
片段2:会话创建(Service)
源码路径:foundation/multimedia/camera_framework/services/camera_service/src/hcamera_service.cpp
int32_t HCameraService::CreateCaptureSession(sptr<ICaptureSession>& session, int32_t opMode)
{
std::lock_guard<std::mutex> lock(mutex_);
sptr<HCaptureSession> captureSession = nullptr;
rc = HCaptureSession::NewInstance(callerToken, opMode, captureSession);
captureSession->SetCameraRotateStrategyInfos(cameraRotateStrategyInfos_);
session = captureSession;
pid_t pid = IPCSkeleton::GetCallingPid();
captureSessionsManager_.EnsureInsert(pid, captureSession);
return rc;
}
逐行分析:
- 服务端加锁,保证并发会话创建安全。
- 用
callerToken + opMode实例化HCaptureSession。 - 注入旋转策略信息,保证后续 Start 有上下文。
- 写回
session给 Framework。 - 按
pid登记,便于并发会话管理和回收。
片段3:输出门禁(Framework)
源码路径:foundation/multimedia/camera_framework/frameworks/native/camera/src/session/capture_session.cpp
bool CaptureSession::CanAddOutput(sptr<CaptureOutput>& output)
{
auto outputType = output->GetOutputType();
std::shared_ptr<Profile> profilePtr = nullptr;
switch (outputType) {
case CAPTURE_OUTPUT_TYPE_PREVIEW:
profilePtr = output->IsTagSetted(CaptureOutput::DYNAMIC_PROFILE) ? GetPreconfigPreviewProfile()
: output->GetPreviewProfile();
break;
case CAPTURE_OUTPUT_TYPE_PHOTO:
profilePtr = output->IsTagSetted(CaptureOutput::DYNAMIC_PROFILE) ? GetPreconfigPhotoProfile()
: output->GetPhotoProfile();
break;
case CAPTURE_OUTPUT_TYPE_VIDEO:
profilePtr = output->IsTagSetted(CaptureOutput::DYNAMIC_PROFILE) ? GetPreconfigVideoProfile()
: output->GetVideoProfile();
break;
case CAPTURE_OUTPUT_TYPE_METADATA:
return true;
default:
return false;
}
CHECK_ERROR_RETURN_RET(profilePtr == nullptr, false);
return ValidateOutputProfile(*profilePtr, outputType);
}
逐行分析:
- 先看
outputType,不同输出类型走不同 profile 源。 DYNAMIC_PROFILE时走预配置 profile,非动态时走输出对象自带 profile。METADATA直接放行,不走图像 profile 校验。- profile 为空直接失败。
- 最终统一交给
ValidateOutputProfile做 mode 能力匹配。
片段4:profile 校验与 fallback(Framework)
源码路径:foundation/multimedia/camera_framework/frameworks/native/camera/src/session/capture_session.cpp
auto validateOutputProfileWithFallback = [modeName, &validateOutputProfileFunc](auto& profileMap,
auto validateProfile, const char* outputName) -> bool {
auto modeIt = profileMap.find(modeName);
if (modeIt != profileMap.end() && validateOutputProfileFunc(validateProfile, modeIt->second)) {
return true;
}
if (modeName != SceneMode::NORMAL) {
auto normalIt = profileMap.find(SceneMode::NORMAL);
if (normalIt != profileMap.end()) {
if (validateOutputProfileFunc(validateProfile, normalIt->second)) {
return true;
}
}
}
return false;
};
逐行分析:
- 先严格按当前
modeName匹配。 - 当前 mode 失败才尝试
NORMALfallback。 - fallback 成功只表示“允许加入会话”,不保证显示链一定稳定。
片段5:提交事务(Service)
源码路径:foundation/multimedia/camera_framework/services/camera_service/src/hcapture_session.cpp
int32_t HCaptureSession::CommitConfig()
{
bool isTransferSupport = stateMachine_.CheckTransfer(CaptureSessionState::SESSION_CONFIG_COMMITTED);
CHECK_ERROR_RETURN_LOG(!isTransferSupport, "... Need to call BeginConfig before committing ...");
if (isNeedCommitting_) {
stateMachine_.Transfer(CaptureSessionState::SESSION_CONFIG_COMMITTED);
return;
}
errorCode = ValidateSession();
CHECK_ERROR_RETURN(errorCode != CAMERA_OK);
errorCode = LinkInputAndOutputs();
CHECK_ERROR_RETURN_LOG(errorCode != CAMERA_OK, "... Failed to commit config ...");
stateMachine_.Transfer(CaptureSessionState::SESSION_CONFIG_COMMITTED);
}
逐行分析:
- 第一道门:状态迁移合法性(没 BeginConfig 直接挡住)。
isNeedCommitting_分支允许直接迁移到 COMMITTED(特定场景)。ValidateSession()做输入输出完整性检查。LinkInputAndOutputs()执行真实建链。- 全部通过才迁移到
SESSION_CONFIG_COMMITTED。
片段6:Link + CreateStreams + CommitStreams(Service)
源码路径:foundation/multimedia/camera_framework/services/camera_service/src/hstream_operator.cpp
int32_t HStreamOperator::LinkInputAndOutputs(const std::shared_ptr<OHOS::Camera::CameraMetadata>& settings,
int32_t opMode)
{
auto allStream = streamContainer_.GetAllStreams();
for (auto& stream : allStream) {
rc = stream->LinkInput(streamOperator_, settings);
CHECK_EXECUTE(stream->GetHdiStreamId() == STREAM_ID_UNSET,
stream->SetHdiStreamId(GenerateHdiStreamId()));
stream->SetStreamInfo(curStreamInfo);
CHECK_EXECUTE(stream->GetStreamType() != StreamType::METADATA,
allStreamInfos.push_back(curStreamInfo));
}
rc = CreateAndCommitStreams(allStreamInfos, settings, opMode);
return rc;
}
逐行分析:
- 遍历当前会话内所有流对象。
- 每个流先
LinkInput,完成输入侧绑定。 - 为未分配流分配
hdiStreamId。 - 把流参数写入
StreamInfo,供 HDI 建流。 - 最后统一调用
CreateAndCommitStreams,形成可运行配置。
片段7:启动事务(Service)
源码路径:foundation/multimedia/camera_framework/services/camera_service/src/hcapture_session.cpp
int32_t HCaptureSession::Start()
{
bool isTransferSupport = stateMachine_.CheckTransfer(CaptureSessionState::SESSION_STARTED);
if (!isTransferSupport) {
errorCode = CAMERA_INVALID_STATE;
return;
}
auto cameraDevice = GetCameraDevice();
uint8_t usedAsPositionU8 = OHOS_CAMERA_POSITION_OTHER;
if (cameraDevice != nullptr) {
settings = cameraDevice->CloneCachedSettings();
usedAsPositionU8 = cameraDevice->GetUsedAsPosition();
}
camera_position_enum_t cameraPosition = static_cast<camera_position_enum_t>(usedAsPositionU8);
errorCode = hStreamOperatorSptr->StartPreviewStream(settings, cameraPosition);
if (errorCode == CAMERA_OK) {
isSessionStarted_ = true;
}
stateMachine_.Transfer(CaptureSessionState::SESSION_STARTED);
}
逐行分析:
- 先检查能否从当前状态迁移到 STARTED。
- 从设备克隆
settings,并读取cameraPosition。 - 调
StartPreviewStream只启动预览流。 - 成功后设置
isSessionStarted_。 - 状态迁移到
SESSION_STARTED。
片段8:StartPreviewStream 仅拉起 PREVIEW
源码路径:foundation/multimedia/camera_framework/services/camera_service/src/hstream_operator.cpp
for (auto& item : repeatStreams) {
auto curStreamRepeat = CastStream<HStreamRepeat>(item);
auto repeatType = curStreamRepeat->GetRepeatStreamType();
if (repeatType != RepeatStreamType::PREVIEW) {
continue;
}
curStreamRepeat->SetUsedAsPosition(cameraPosition);
errorCode = curStreamRepeat->Start(settings);
if (errorCode != CAMERA_OK) {
break;
}
}
逐行分析:
- 遍历 repeat 流集合。
- 非 PREVIEW 流直接跳过。
- 对预览流写入
cameraPosition。 - 调
Start(settings)启动预览。 - 任一预览流失败会中断并返回错误。
本章信号 -> 判断 -> 动作
| 信号 | 判断 | 动作 |
|---|---|---|
Need to call BeginConfig before committing |
状态机时序错误,Commit 前未进入配置态 | 回查 BeginConfig 是否实际执行且无异常中断 |
No inputs present |
仅创建了输出,输入设备未绑定 | 回查 AddInput 调用顺序与返回值 |
No outputs present |
输出未加入会话或加入失败 | 回查 AddOutput 和 CanAddOutput/ValidateOutputProfile |
CanAddOutput check failed |
profile 与 mode 不匹配 | 对照能力集检查 ValidateOutputProfile 的 mode/fallback 路径 |
Failed to commit config |
Link/Create/CommitStreams 阶段失败 | 分段看 LinkInputAndOutputs、CreateStreams、CommitStreams |
Need to call after committing |
Start 时还没进入 COMMITTED | 回查 Commit 是否通过以及状态是否迁移 |
Start execute success 但无画面 |
控制链成功,不等于显示链成功 | 跳第5章核查 profile + surface + session 绑定和运行包一致性 |
跨章连接
| 本章知识点 | 跳转章节 | 原因 |
|---|---|---|
| mode/profile 门禁机制 | 第3章 | 能力数据来源在 HDF/HDI 注入层 |
| 控制链成功但显示失败 | 第5章 | 显示绑定问题在 ArkTS output + surface |
| 具体函数断点定位 | 第6章 | 函数级走读包含更细粒度输入输出约束 |
| 快速排障命令与证据模板 | 第8章 | 统一命令和证据格式在调试体系章 |
本章最小动作
- 先按函数覆盖清单确认日志里是否出现
BeginConfig/AddInput/AddOutput/CommitConfig/Start。 - 若
CommitConfig失败,先看ValidateSessionInputs/Outputs,再看LinkInputAndOutputs。 - 若
Start成功但黑屏,立即转第5章做输出绑定核查,不在第4章重复试错。
发布后补链
- 上一篇:https://laval.csdn.net/69d8b86154b52172bc68609a.html
- 下一篇:https://laval.csdn.net/69d8b91954b52172bc6860be.html
全章导航
- 第0章 导读学习指南:https://laval.csdn.net/69d77a0554b52172bc6802aa.html
- 第1章 主链调用总览(图表):https://laval.csdn.net/69d8b75f54b52172bc686020.html
- 第2章 驱动与硬件基线:https://laval.csdn.net/69d8b7fd0a2f6a37c59e6f33.html
- 第3章 能力注入与流桥接(HDF/HDI/VDI):https://laval.csdn.net/69d8b86154b52172bc68609a.html
- 第4章 会话编排与门禁(Framework/Service):https://laval.csdn.net/69d8b8d154b52172bc6860ae.html
- 第5章 输出创建与显示绑定(ArkTS/HAP):https://laval.csdn.net/69d8b91954b52172bc6860be.html
- 第6章 函数级链路走读(驱动到显示):https://laval.csdn.net/69d8b96854b52172bc6860cd.html
- 第7章 异常挂点与主链归因:https://laval.csdn.net/69d8b9d054b52172bc6860dc.html
- 第8章 调试方法与证据模板:https://laval.csdn.net/69d8ba1454b52172bc6860e4.html
- 第9章 实战演练与复盘:https://laval.csdn.net/69d8ba4754b52172bc6860f3.html
更多推荐
所有评论(0)