本文为《开源鸿蒙相机:驱动到应用预览显示》系列发布版。
当前章节:第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)

本章回答的问题

  1. Session 是什么,为什么必须有 Session,而不是直接 open 后就 start。
  2. Session 有哪些关键参数和状态,这些参数/状态分别在什么位置读取和生效。
  3. Session 的核心机制和执行流程是什么,为什么这样设计。
  4. 全链路函数调用是否覆盖完整,每个函数在图里负责什么。

Session 的定义与必要性

定义(源码定义)

源码路径:foundation/multimedia/camera_framework/interfaces/inner_api/native/camera/include/session/capture_session.h

CaptureSession 是 Framework 侧“输入设备 + 输出流 + 模式参数 + 启停状态”的事务容器,核心接口是:

  • BeginConfig
  • AddInput
  • AddOutput
  • CommitConfig
  • Start/Stop

对应锚点:

  • foundation/multimedia/camera_framework/interfaces/inner_api/native/camera/include/session/capture_session.h:385-460

为什么必须有 Session

如果没有 Session,应用侧把输入输出直接逐条下发,会出现三个问题:

  1. 无法保证原子性:输入刚挂上、输出还没挂完就触发启动,流配置容易半成品。
  2. 无法保证时序合法:StartCommitBegin 顺序混乱时,系统无法做统一门禁。
  3. 无法做模式级校验:SceneModeprofilestreamType 的一致性无法集中判定。

对应源码证据:

  • 状态机强制时序: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

为什么要状态机

  1. 把“调用顺序错误”前置成可解释错误,而不是运行时随机失败。
  2. 把“配置事务”和“运行事务”分离,便于定位到底是配置失败还是启动失败。
  3. 支持“已启动后回到配置态”的安全重配置路径。

Session 在整体中的作用与定位

在全链路里的位置

Session 位于“能力确定之后、建流启动之前”的中枢层,既不是纯应用逻辑,也不是纯驱动逻辑,它负责把多模块能力拼装成一个可运行事务:

  1. 上接能力侧:消费 profile + mode + streamType(能力来源见第3章)。
  2. 中间编排:完成 input/output 组装、状态迁移、提交门禁。
  3. 下接执行侧:触发 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) AddInputICameraDeviceService 绑定进会话 确保会话有可用输入源,否则 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章: 验证门禁函数覆盖是否完整

为什么这样分章

  1. 第3章回答“能力从哪里来”。
  2. 第4章回答“能力怎样被组织并合法提交”。
  3. 第5章回答“应用如何把显示绑定真正落地”。
  4. 第6章回答“当链路异常时,函数级证据怎么拿”。

Session 上下游接口契约(避免章节割裂)

链路位置 上游提供给 Session 的输入 Session 的处理动作 Session 输出给下游 下游消费点
能力侧 -> Session modeProfileMapoutput profilestreamType 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

契约破坏时的典型表现

  1. 能力契约破坏:CanAddOutput check failed,说明 profile 不被 mode 接受。
  2. 输入契约破坏:No inputs present,说明未完成 input 绑定。
  3. 输出契约破坏:No outputs presentrepeatStream is nullptr,说明输出挂载链不完整。
  4. 提交契约破坏:Failed to commit config,说明 Link/Create/CommitStreams 阶段失败。
  5. 启动契约破坏:Need to call after committingFailed 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;
}

逐行分析:

  1. 先拿 serviceProxy,没有服务代理则不能创建会话。
  2. SceneMode -> OperationMode 做语义桥接。
  3. 通过 serviceProxy->CreateCaptureSession 申请远端 ICaptureSession
  4. CreateCaptureSessionImpl 决定具体子类(VideoSession/PhotoSession/...)。
  5. 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;
}

逐行分析:

  1. 服务端加锁,保证并发会话创建安全。
  2. callerToken + opMode 实例化 HCaptureSession
  3. 注入旋转策略信息,保证后续 Start 有上下文。
  4. 写回 session 给 Framework。
  5. 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);
}

逐行分析:

  1. 先看 outputType,不同输出类型走不同 profile 源。
  2. DYNAMIC_PROFILE 时走预配置 profile,非动态时走输出对象自带 profile。
  3. METADATA 直接放行,不走图像 profile 校验。
  4. profile 为空直接失败。
  5. 最终统一交给 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;
};

逐行分析:

  1. 先严格按当前 modeName 匹配。
  2. 当前 mode 失败才尝试 NORMAL fallback。
  3. 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);
}

逐行分析:

  1. 第一道门:状态迁移合法性(没 BeginConfig 直接挡住)。
  2. isNeedCommitting_ 分支允许直接迁移到 COMMITTED(特定场景)。
  3. ValidateSession() 做输入输出完整性检查。
  4. LinkInputAndOutputs() 执行真实建链。
  5. 全部通过才迁移到 SESSION_CONFIG_COMMITTED

源码路径: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;
}

逐行分析:

  1. 遍历当前会话内所有流对象。
  2. 每个流先 LinkInput,完成输入侧绑定。
  3. 为未分配流分配 hdiStreamId
  4. 把流参数写入 StreamInfo,供 HDI 建流。
  5. 最后统一调用 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);
}

逐行分析:

  1. 先检查能否从当前状态迁移到 STARTED。
  2. 从设备克隆 settings,并读取 cameraPosition
  3. StartPreviewStream 只启动预览流。
  4. 成功后设置 isSessionStarted_
  5. 状态迁移到 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;
    }
}

逐行分析:

  1. 遍历 repeat 流集合。
  2. 非 PREVIEW 流直接跳过。
  3. 对预览流写入 cameraPosition
  4. Start(settings) 启动预览。
  5. 任一预览流失败会中断并返回错误。

本章信号 -> 判断 -> 动作

信号 判断 动作
Need to call BeginConfig before committing 状态机时序错误,Commit 前未进入配置态 回查 BeginConfig 是否实际执行且无异常中断
No inputs present 仅创建了输出,输入设备未绑定 回查 AddInput 调用顺序与返回值
No outputs present 输出未加入会话或加入失败 回查 AddOutputCanAddOutput/ValidateOutputProfile
CanAddOutput check failed profile 与 mode 不匹配 对照能力集检查 ValidateOutputProfile 的 mode/fallback 路径
Failed to commit config Link/Create/CommitStreams 阶段失败 分段看 LinkInputAndOutputsCreateStreamsCommitStreams
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章 统一命令和证据格式在调试体系章

本章最小动作

  1. 先按函数覆盖清单确认日志里是否出现 BeginConfig/AddInput/AddOutput/CommitConfig/Start
  2. CommitConfig 失败,先看 ValidateSessionInputs/Outputs,再看 LinkInputAndOutputs
  3. Start 成功但黑屏,立即转第5章做输出绑定核查,不在第4章重复试错。

发布后补链

全章导航

Logo

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

更多推荐