已合并
fix foreground #20360
fix foreground #20360
已合并
xhz-sz创建于 7 天前
xhz-sz
xhz-sz
7 天前

IssueNo: https://gitcode.com/openharmony/ability_ability_runtime/issues/16115

Description:

稳定性自检:

自检项 自检结果
涉及跨进程调用的相关操作需要抛至主线程或加锁防止并发
成员变量进行赋值或创建需要排查并发
谨慎在lambda表达式中使用引用捕获
谨慎在未经拷贝的情况下使用外部传入的string、C字符串
map\vector\list\set等stl模板类使用时需要排查并发
谨慎考虑加锁范围
在IPC通信中谨慎使用同步通信方式
禁止传递this指针至其他模块或线程(特别是eventhandler任务)
禁止将外部传入的裸指针在内部直接构造智能指针
禁止多个独立创建的智能指针管理同一地址
禁止在析构函数中抛异步任务
禁止js对象在非js线程(例如在IPC线程)创建、使用或销毁
禁止在对外接口中未经判空直接使用外部传入的指针
禁止接口返回局部变量引用
禁止在信号函数中加锁
禁止在关键流程(SA启动、应用启动等主流程)执行耗时的操作
禁止将同一个cpp编译在不同的so中

安全编码自检:

自检项 自检结果
裸指针避免通过隐式转换构造为sptr
json对象在取值之前必须先判断类型,避免类型不匹配
序列化时必须对传入的数组大小进行校验,避免出现超大数组
避免使用未明确位宽的整型,选择使用int8_t、uint8_t等类型
外部传入的路径要做规范化校验,对路径中的.、..、../等特殊字符严格校验
指针变量、表示资源描述符的变量、bool变量必须赋初值
readParcelable获取的对象使用前需要判空
分配和释放内存的函数需要成对出现
申请内存后异常退出前需要及时进行内存释放
内存申请前必须对内存大小进行合法性校验
内存分配后必须判断是否成功
禁止使用realloc、alloca函数
禁止打印文件路径、口令等敏感信息,如有需要,使用private修饰
禁止打印内存地址
整数之间运算时必须严格检查,确保不会出现溢出、反转、除0
禁止对有符号整数进行位操作符运算
禁止对指针进行逻辑或位运算
循环次数如果收外部数据控制,需要检验其合法性
禁止使用内存操作类危险函数,需要使用安全函数
谨慎使用不可重入函数
必须检查安全函数的返回值,并进行正确处理
禁止仅通过TokenType类型判断绕过权限校验

TDD Result:

XTS Result:

是否已执行L0用例

AI检视评分(使用本地代码检视skills扫描):

代码检视报告 — PR #20360 OnAbilityRequestDone 白名单修复(Round 4 / 最新提交)

统一报告由 codecheck 工作台生成,用于门禁管控。Round 4:commit 更新为 41928933("fix state"),diff 内容与 Round 3 一致,全 pattern 逐条复核。


报告元数据

codecheck_report:
  schema_version: "1.0"
  scope: "PR20360-OnAbilityRequestDone-whitelist"
  round: 4
  commit_id: "419289331a16b6d1da8bff820ab4177cb278f7e6"
  change_id: "N/A"
  report_id: "41928933-R4"
  date: "2026-09-03"
  gate_decision: "approve"
  risk_level: "low"
  score: 96
  dimensions_required: ["security-scanner", "logic-scanner", "input-scanner"]
  dimensions_executed: ["security-scanner", "logic-scanner", "input-scanner"]
  findings_total: 2
  findings_by_severity: {P0: 0, P1: 0, P2: 0, P3: 2}
  gate_blockers: []
  must_fix: []
  followups: ["LOG-01", "INP-01"]

1. 门禁结论

项目 结论
决策 approve
风险等级 🟢 low
评分 96/100
阻塞项
必须修复(P0/P1) 0 项
建议跟进(P2/P3) 2 项

一句话结论:将 OnAbilityRequestDone 的黑名单守卫(仅拦 FOREGROUNDING)改为白名单(放行 BACKGROUND/INITIAL/INACTIVE/ACTIVE),在异步回调时点重新校验 DoForegroundUIExtension 的全部生命周期前置条件,修复高频振荡场景下 state 卡死 FOREGROUNDING 的问题,同时覆盖预加载和 connect-then-start 场景;三维度全 pattern 复核无 P0/P1。


2. 扣分原因(仅 gate_decision=block 时呈现;approve/conditional/insufficient 时本节省略)


3. 必须立即处理(P0/P1)

无。


4. 建议本轮或下一补档处理(P2/P3)

ID 优先级 问题 建议行动 排期
LOG-01 P3 测试仅覆盖 skip 路径(FOREGROUNDING/FOREGROUND),未覆盖 allow 路径(BACKGROUND/INITIAL/INACTIVE/ACTIVE) 后续补充 mock scheduler 使 allow 路径可测;优先覆盖 INACTIVE(预加载)和 BACKGROUND(振荡) 下一补档
INP-01 P3 测试文件中 UIEXTENSION_LAUNCH_TIMESTAMP_HIGH 常量与 ability_record.cpp:106 重复定义 导出或 include 共享定义,避免维护时遗漏同步修改 下一补档

5. 分维度速览

维度 结果 关键说明
security-scanner ✅ 通过 G12 竞争:serialMutex_ 全程持锁,check-then-act 原子化;修复 LOG-008 状态机死锁(FOREGROUND→FOREGROUNDING→app 丢弃→卡死);超时安全不变量(state=FOREGROUND ⟹ RemoveForegroundTimeoutTask 已执行);INACTIVE/ACTIVE 放行后重复回调仍被 FOREGROUND 拦截;11 项检查全部通过,G11/G12 横扫无同类
logic-scanner ✅ 通过 LOG-003 枚举覆盖完整:白名单 {INITIAL(0),INACTIVE(1),ACTIVE(2),BACKGROUND(10)} 与 DoForegroundUIExtension 前置条件(!INACTIVATING && !FOREGROUNDING && !BACKGROUNDING,排除 FOREGROUND)完全对齐且为严格子集;LOG-006 状态转换合法(INACTIVE→FOREGROUNDING→FOREGROUND,ACTIVE→FOREGROUNDING→FOREGROUND);LOG-007 单一状态源;pendingState 兜底链路完整;RemoveUIExtensionLaunchTimestamp 放置于 ForegroundUIExtensionAbility 之后
input-scanner ✅ 通过 token 经 GetExtensionByTokenFromServiceMap + CHECK_POINTER 校验;state 经 ConvertToAppAbilityState + early return 校验(仅 FOREGROUND/BACKGROUND 有效,其余→UNDEFINED→return);sessionInfo null 安全(三元兜底 -1);LOG-009 错误路径完整;无新 IPC 接口暴露;无 DB/文件持久化 sink

6. 关键发现详情

[LOG-01] 测试未覆盖 allow 路径(P3, scanner=logic-scanner)

  • 位置test/unittest/ui_extension_ability_manager_third_test/ui_extension_ability_manager_third_test.cpp:120-175
  • 触发路径:OnAbilityRequestDone_001 测 FOREGROUNDING skip(:131 SetAbilityState(FOREGROUNDING),:142 传 ABILITY_STATE_FOREGROUND),_002 测 FOREGROUND skip(:162 SetAbilityState(FOREGROUND),:173 传 ABILITY_STATE_FOREGROUND)。两个用例均设非 allow 状态,走 else skip 路径(:373 TAG_LOGW),均未测 BACKGROUND/INITIAL/INACTIVE/ACTIVE allow 路径
  • 影响:allow 路径(ForegroundUIExtensionAbility + RemoveUIExtensionLaunchTimestamp)未被单测覆盖;特别是 INACTIVE(预加载场景)和 ACTIVE(connect-then-start 场景)是新补充的白名单状态,缺乏回归保护。断言仅验证 timestamp 未被删除(:143/:174 EXPECT_NE ... -1),未验证 allow 路径下 timestamp 被清除
  • 证据:两个测试用例均设置非 allow 状态(FOREGROUNDING/FOREGROUND),走 skip 路径,allow 路径无覆盖
  • 建议:后续引入 mock ability scheduler,使 allow 路径可验证 ForegroundUIExtensionAbility 被调用且 timestamp 被清除;优先覆盖 INACTIVE(预加载)和 BACKGROUND(正常振荡)

[INP-01] 常量重复定义(P3, scanner=input-scanner)

  • 位置test/unittest/ui_extension_ability_manager_third_test/ui_extension_ability_manager_third_test.cpp:41 vs services/abilitymgr/src/ability_record.cpp:106
  • 触发路径:测试文件 anonymous namespace(:40-42)定义 UIEXTENSION_LAUNCH_TIMESTAMP_HIGH = "ohos.ability.params.uiExtensionLaunchTimestampHigh";ability_record.cpp:106 定义 constexpr const char* UIEXTENSION_LAUNCH_TIMESTAMP_HIGH = "ohos.ability.params.uiExtensionLaunchTimestampHigh",两处独立定义相同字符串值,无 include 共享
  • 影响:若 ability_record.cpp 中的常量值变更,测试文件不会同步,导致测试断言误判(GetIntParam 使用字符串 key 查询 Want 参数)
  • 证据:两处定义相同字符串值,无 include 关系
  • 建议:将 ability_record.cpp:106-107 的常量声明提升到头文件,测试文件 include 引用

附:修复方案技术摘要

根因

DoForegroundUIExtensionMoveToForegroundOnAbilityRequestDone(异步 IPC 回调)之间存在时序鸿沟。黑名单守卫仅拦截 FOREGROUNDING,漏放 FOREGROUND 状态——高频振荡中两次 MoveToForeground 的回调交错到达,先到的完成前台(state→FOREGROUND),后到的未被拦截,调 ForegroundUIExtensionAbility 把 state 打回 FOREGROUNDING 并发重复 ForegroundNew,应用侧 lifecycleState_ 已是 5 → "lifecycle state equal" 丢弃 → 无 AbilityTransitionDone 回调 → 卡死(LOG-008 状态机死锁)。

修复

黑名单改白名单:放行 BACKGROUND/INITIAL/INACTIVE/ACTIVE,在异步回调时点重新校验 DoForegroundUIExtension 的全部生命周期前置条件。

白名单状态与 DoForegroundUIExtension 前置条件对齐:

白名单放行 到达场景 来源
INITIAL 0 首次加载后前台 AttachAbilityThreadInner → MoveToForeground
INACTIVE 1 预加载完成后前台 Inactivate → DispatchInactive → DoForegroundUIExtension
ACTIVE 2 connect 后再 start CommandAbility → DoForegroundUIExtension
BACKGROUND 10 正常后台→前台 CompleteBackground → DoForegroundUIExtension

白名单拦截:FOREGROUND(9,防重复卡死)、FOREGROUNDING(11,防重复)、BACKGROUNDING(12,防干扰)、INACTIVATING(5,防干扰)、ACTIVATING(6,防干扰)、TERMINATING(8,终止中)、及所有 FAILED/INVALID/FREEZED/DO_NOTHING 状态。

白名单是 DoForegroundUIExtension 前置条件允许集的严格子集(额外排除 FOREGROUND/ACTIVATING/TERMINATING/FAILED 状态),保证异步回调时点更保守地校验,正确性不受影响。

Pattern 逐条复核

Pattern 检查点 结论
G11 生命周期状态机 状态转换合法,无非法跳转 ✅ INITIAL/INACTIVE/ACTIVE/BACKGROUND→FOREGROUNDING→FOREGROUND 均合法
G12 条件竞争 回调注册/触发有锁保护 ✅ serialMutex_ 全程持锁
CONC-001 死锁/锁顺序 持锁时不回调外部代码 ✅ 本 PR 未引入新 IPC-in-lock(ForegroundUIExtensionAbility 在锁内调用是既有行为,PR 未改变)
CONC-002 Check-Then-Act check-then-act 原子化 ✅ 锁内完成 state 检查 + ForegroundUIExtensionAbility 调用
LOG-001 死代码 无不可达代码 ✅ early-return 结构清晰
LOG-002 逻辑矛盾 无互斥条件同时为真
LOG-003 条件覆盖不完整 枚举全分支覆盖 ✅ 白名单 4 状态 + else 兜底全部剩余
LOG-006 非法状态转换 无跳过中间状态 ✅ 均经 FOREGROUNDING 中间态
LOG-007 状态不一致 单一状态源 ✅ GetAbilityState/SetAbilityState 单源
LOG-008 状态机死锁 无无法到达终态的循环 ✅ 修复了原 FOREGROUND→FOREGROUNDING 死锁
LOG-009 遗漏错误路径 错误返回值检查 ✅ CHECK_POINTER + early return + ternary null safety
MEM-001 空指针 解引用前判空 ✅ CHECK_POINTER(abilityRecord) + sessionInfo 三元兜底
MEM-003 UAF/生命周期 异步回调持有对象安全 ✅ shared_ptr 从 map 查找,nullptr 被 CHECK_POINTER 拦截
MEM-004 整数溢出 类型转换安全 ✅ static_cast<int32_t> 枚举→int 安全
RES-001 资源泄漏 RAII + shared_ptr ✅ lock_guard RAII,无裸资源分配
AUTH-001 敏感信息 日志无敏感数据 ✅ 仅 bundleName/abilityName/int 值,无路径/口令/地址
IPC-005~010 IPC 鉴权 回调入口安全 ✅ 非直接 IPC 入口,token 作 lookup key
likedislike
Pull Request已成功合入, 合并人@openharmony_ci
(感谢 xhz-sz 的贡献)
afwk_helper成员
7 天前 评论:

开始进行AI检视!

AI review has been started, please wait...

likedislike
afwk_helper成员
7 天前 评论:
check type result report
start ai_review pass -
likedislike
xhz-szxhz-sz
7 天前 修改了pull request 的描述
xhz-sz
xhz-sz
7 天前 评论:

static-check

likedislike
openharmony_ciopenharmony_ci成员
7 天前 添加了label:waiting_on_author
此处折叠了122条消息 查看更多
wkljywkljy成员
6 天前 通过审查
openharmony_ciopenharmony_ci成员
6 天前 关闭了关联的issue
openharmony_ciopenharmony_ci成员
6 天前 合入了pull request,合并节点 SHA:b075c697a766efe2361247cdaa55345bb96443fe
openharmony_ciopenharmony_ci成员
6 天前 删除了label:waiting_for_review
openharmony_ciopenharmony_ci成员
6 天前 添加了label:merged