已开启
docs: add DFR reliability review report for service-side code #4978
wangsen1994创建于 8月12日
docs: add DFR reliability review report for service-side code #4978
已开启
共 1 个文件变更+199-0
| @@ -0,0 +1,199 @@ | |||
| 1 | +# 代码可靠性评审报告(DFR) | ||
| 2 | + | ||
| 3 | +## 评审配置 | ||
| 4 | +- **代码范围**: `services/ans/`、`services/distributed/`、`services/domain/`、`services/infrastructure/`(排除 `services/reminder/`) | ||
| 5 | +- **可靠性目标**: 服务不卡死/不挂死、进程不崩溃/OOM、通知业务不中断 + 通用风险扫描 | ||
| 6 | +- **执行路径**: 双路径(自上而下 + 自下而上) | ||
| 7 | +- **检查对象**: 网络/分布式、数据/持久化、线程并发、内存/资源泄漏 | ||
| 8 | +- **故障模式库**: 内置扩展版(11大类60+故障模式:H/I/T/M/P/F/D/NET/CS/DS/A/AF类) | ||
| 9 | +- **并行度**: 3(3个 subagent 并行分析三个独立区域) | ||
| 10 | +- **评审日期**: 2026-08-12 | ||
| 11 | + | ||
| 12 | +--- | ||
| 13 | + | ||
| 14 | +## 一、架构与设计问题(D级)— 优先处理 | ||
| 15 | + | ||
| 16 | +| 分析对象 | 分析子对象 | 失效模式 | 失效原因 | 失效影响 | 定位方法(补充具体日志) | 故障注入方法(和测试对齐) | 严酷度 | 恢复 | 现有改进需求 | 新增改进需求 | 维度 | 备注(beta单、问题单) | 刷新责任人 | | ||
| 17 | +| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | | ||
| 18 | +| advanced_notification_service.cpp:1657,2412 等 | notificationList_ 全局访问(GetAllNotification/TriggerAutoDelete/GetNotificationsByBundle等数十处) | T-03 数据竞争 | 核心数据结构 `notificationList_` 在大量函数中直接遍历/修改**不持任何锁**,仅依赖 `notificationSvrQueue_` 串行化但并非所有路径经过队列。对比 `triggerNotificationList_`/`delayNotificationList_` 有独立 mutex,设计遗漏明确 | 并发遍历时另一线程修改→迭代器失效→UAF→ANS进程崩溃→所有通知功能不可用→系统级通知服务瘫痪 | faultlog崩溃栈(SIGSEGV)落在list迭代器;TSA报告;高并发发布+dump查询触发 | 高频发布通知同时通过dump接口调用GetAllNotification,观察是否崩溃 | I | 系统层(appspawn保活重启) | triggerNotificationList_和delayNotificationList_有独立mutex | 为notificationList_增加专属mutex,所有访问路径强制持锁或经队列提交 | 线程 | 三路径交叉验证命中;推理风险待动态验证 | - | | ||
| 19 | +| advanced_notification_service.cpp:2362; 1087; geofence_service.cpp:781等; advanced_notification_utils.cpp:2637; snooze_delay_manager.cpp:259; extension_service_connection.cpp:134; distributed_database.cpp:119; distributed_screen_status_manager.cpp:57; distributed_rdb_helper.cpp:153; distributed_client.cpp:68; distributed_unlock_listener_oper_service.cpp:49; distributed_operation_helper.cpp:75; distributed_database.cpp:328; bundle_manager_helper.cpp:48 | 持锁期间发起同步IPC/外部阻塞调用(PushCheck/IsDoNotDisturbEnabled/ExecuteCancelGroup/geofence/RemoveAppObserver/TriggerSnoozeDelay/NotifyOnReceiveMessage/CheckKvStore/OnDeviceDisconnected/InsertData/ReleaseDevice/AddDelayTask/TriggerOperation/RecreateDistributedDB/OnRemoteDied)共13+处 | T-02 死锁 / I-02 IPC调用阻塞 | 系统性设计缺陷:持`pushMutex_`/`notDisturbEnableStateMutex_`/`triggerNotificationMutex_`/`appObserverLock_`/`snoozeNotificationMutex_`/`mutex_`/`rdbStorePtrMutex_`/`clientLock_`/`mapLock_`/`operationMutex_`/`connectionMutex_`等锁期间,调用同步IPC(OnCheckNotification/QueryByDataShare/UnregisterApplicationStateObserver/DeleteKvStore/GetSingleKvStore/SendRequest/StartAbility等)或阻塞IO(DB操作),无超时保护 | 持锁线程IPC阻塞→锁长期持有→并发调用同锁的函数全部阻塞→IPC线程池逐步耗尽→ANS服务不响应→系统级卡死 | watchdog THREAD_BLOCK事件;全线程堆栈dump显示互等;IPC调用耗时统计 | 对端服务注入死循环/sleep;慢速设备压测;构造ExtensionAbility被冻结场景 | I | 系统层(Binder默认超时5s+看门狗) | 部分函数有缓存逻辑跳过IPC;recursive_mutex避免同线程重入 | 锁内仅拷贝引用/参数后释放锁,锁外执行IPC;增加IPC超时;改用异步IPC(MessageOption::TF_ASYNC) | 线程/接口 | 双路径交叉验证命中(13+处);最高优先级系统性问题 | - | | ||
| 20 | +| distributed_database.cpp:58; distributed_screen_status_manager.cpp:107 | DeviceInitCallBack::OnRemoteDied(空实现) | I-01 对端进程死亡 | OnRemoteDied回调**仅打日志无任何恢复动作**(不清理kvDataManager_、不重连、不通知上层)。DeviceManager死亡后kvDataManager_仍非空,CheckKvDataManager()通过但底层连接已断,后续GetSingleKvStore等持续失败 | DeviceManager死亡→OnRemoteDied空操作→kvDataManager_未清理→后续操作持续失败→分布式通知同步全链路静默失效→通知业务中断且无恢复 | OnRemoteDied回调日志;分布式同步成功率下降;GetSingleKvStore错误码日志 | kill DeviceManager服务进程后触发分布式通知同步,观察是否静默失败 | I | 无 | 无 | OnRemoteDied中清理kvDataManager_(置null)和kvStore_,触发下次CheckKvManager重新初始化;增加重连退避;通知上层触发恢复 | 网络/进程 | 双路径交叉验证命中 | - | | ||
| 21 | +| distributed_socket.cpp:226,215 | ClientSendMessage→::SendMessage / ::SendBytes | P-05a Socket接收超时 / I-14 消息无响应 | 软总线同步发送接口::SendMessage/::SendBytes**无超时保护**,socket未设SO_RCVTIMEO,消息发送后无超时/重试。对端处理慢/网络分区/软总线底层阻塞时调用线程永久挂起 | SendMessage阻塞→调用线程(ffrt任务/IPC线程)永久挂起→该线程后续消息排队→消息队列积压→分布式通知发布/删除全部中断→服务卡死 | 调用线程堆栈停在::SendMessage;消息队列深度统计;分布式同步耗时监控 | 断开网络后触发SendMessage;对端设备注入sleep;kill软总线进程后触发发送 | I | 系统层(软总线底层可能有部分超时,不确定) | 发送适配器层ffrt::submit异步化(distributed_send_adapter.cpp:65);ClientBind有QoS参数 | 为::SendMessage增加超时包装(独立线程+future+wait_for);失败后重试与退避;监控发送耗时超阈值上报HiSysEvent | 网络 | 单路径命中但传播链完整 | - | | ||
| 22 | +| distributed_send_adapter.cpp:81 | SendPackage→packageCached_队列 | I-16 消息过载/流控失效 / M-05 内存水位失控 | `packageCached_`队列**无大小上限**。isRunning为true或队列非空时新PackageInfo直接push_back。消息生产速率(通知发布/删除)高于消费速率(DoSendPackage串行+可能阻塞的SendMessage)时队列无限增长,每条含NotificationRequest序列化数据(数KB~数十KB) | 高频通知发布→packageCached_无限增长→内存持续膨胀→OOM→进程被系统杀死→通知服务整体不可用 | HiAppEvent资源泄漏事件(pss超限);hidumper内存采样;packageCached_.size()监控 | 高频发布通知(>1000条/秒)压测,观察packageCached_增长和PSS变化 | I | 无 | 有串行化处理(DoSendPackage串行执行) | 设置packageCached_最大深度(如1000),超限丢弃非关键消息并上报HiSysEvent;增加背压机制;消息优先级分类 | 网络/进程/内存 | 单路径命中但逻辑明确 | - | | ||
| 23 | +| distributed_device_service.cpp:329-333 | GetDeviceList(返回引用版本) | T-03 数据竞争 | GetDeviceList()持mapLock_返回peerDevice_的**引用**,锁在函数返回时释放。调用者获得内部map的未保护引用,其他线程可并发修改peerDevice_(AddDeviceInfo/DeleteDeviceInfo等) | 并发修改map→调用者遍历引用时迭代器失效→未定义行为(崩溃或数据错乱)→进程崩溃→通知服务中断 | faultlog崩溃栈;TSA报告 | 并发调用GetDeviceList和AddDeviceInfo,观察是否崩溃 | I | 无 | 有同名值传递版本(Line 335-341)做了安全拷贝 | 删除返回引用版本或改为返回值拷贝;若性能敏感用shared_ptr<map>写时复制 | 线程 | 单路径命中但代码证据明确 | - | | ||
| 24 | +| notification_rdb_data_mgr.cpp:316-323 | RdbStoreDataCallBackNotificationStorage::onCorruption | H-05 删除非本模块创建的数据 / D-01 数据库损坏 | 数据库损坏回调中直接调用DeleteRdbStore删除整个数据库文件,**无备份、无尝试恢复、返回值未检查**。损坏后所有通知偏好数据(DND配置/渠道设置/角标配置)全部丢失且不可恢复 | 数据库损坏→onCorruption→DeleteRdbStore删除文件→所有偏好数据丢失→通知行为回退默认值(DND失效/渠道配置丢失/角标重置)→用户通知体验严重降级;DeleteRdbStore失败时数据库半删除状态 | RDB错误日志;onCorruption日志;通知偏好重置现象;GetRdbStore返回E_SQLITE_CORRUPT | 构造数据库文件损坏(截断/写入垃圾数据)后触发通知操作 | I | 系统层(进程重启后Init重建) | 有RecoverDatabase机制(Destroy+Init)但onCorruption路径只删除不重建 | onCorruption中先备份损坏文件(rename而非delete);检查DeleteRdbStore返回值并上报;删除后触发Init重建 | 数据/高危操作 | 单路径命中但证据明确 | - | | ||
| 25 | +| notification_rdb_data_mgr.cpp(全文件) | InsertData/DeleteData/InsertBatchData/DeleteBatchData/ProcessRow | D-02 事务未提交 / F-01a 掉电窗口 | 全文件搜索BeginTransaction/Commit/Rollback**无任何结果**。所有Insert/Delete操作未用事务包裹。InsertBatchData用BatchInsert但不保证原子性。DeleteBatchData多表分批Delete,任一表删除后掉电已删数据不回滚。ProcessRow(OnUpgrade)删除+插入两步无事务 | 多步写入掉电/进程被杀→部分数据已写入部分未写入→数据不一致→通知偏好状态错乱(如DND时间段只更新一半)→业务行为异常 | 通知偏好异常现象;DB一致性校验;掉电压测后对比DB状态 | 写入过程中强制掉电/kill进程,重启后检查数据一致性 | II | 无 | 无 | 所有多步写入用BeginTransaction/Commit/Rollback包裹;RAII事务对象确保异常路径自动Rollback;确认journalMode/syncMode配置 | 数据 | 单路径命中但全文件无事务证据明确 | - | | ||
| 26 | +| notification_rdb_data_mgr.cpp:1181-1215, 451-456 | RecoverDatabase / InsertData恢复路径 | T-03 数据竞争 | InsertData在Line451释放rdbStorePtrMutex_后在Line453调用RecoverDatabase,但isRecovering_在Line1191才设置。释放锁到设置标志间存在**竞态窗口**,其他线程可通过isRecovering_检查(仍false)、获取锁、在已损坏rdbStore_上操作。Destroy置rdbStore_为nullptr但其他线程可能已持有引用 | 线程A触发RecoverDatabase→线程B在窗口期通过检查并获取rdbStore_引用→Destroy置空但线程B仍持引用→线程B在已关闭DB对象上操作→崩溃或数据进一步损坏 | faultlog崩溃栈;并发DB操作错误日志;isRecovering_状态日志 | 并发触发E_SQLITE_CORRUPT后的InsertData,观察是否崩溃 | II | 代码层(try_lock防止重入+isRecovering_标志) | try_lock防止恢复重入;isRecovering_标志存在但设置时机过晚 | 释放rdbStorePtrMutex_前设置isRecovering_=true;持锁状态下调用RecoverDatabase作为原子操作;其他线程检测到isRecovering_后等待重试 | 线程/数据 | 双路径交叉验证命中(风险点3/10) | - | | ||
| 27 | +| distributed_server.cpp:36-48 | ReleaseServer / InitServer(serverSocket_) | T-03 数据竞争 | `serverSocket_` map的遍历/clear/插入**无锁保护**。ReleaseServer先操作serverSocket_再获取serverLock_,InitServer直接操作不获取锁。init原子变量提供初始检查但非充分保护 | 并发操作serverSocket_→迭代器失效→崩溃或数据错乱→服务进程崩溃 | faultlog崩溃栈;TSA报告 | 并发调用ReleaseServer和InitServer | II | 代码层(init原子变量初始检查) | peerSockets_有serverLock_保护 | 为serverSocket_增加锁保护;或用init原子变量CAS操作确保互斥 | 线程 | 单路径命中,置信度中 | - | | ||
| 28 | + | ||
| 29 | +--- | ||
| 30 | + | ||
| 31 | +## 二、编码问题(C级) | ||
| 32 | + | ||
| 33 | +| 分析对象 | 分析子对象 | 失效模式 | 失效原因 | 失效影响 | 定位方法(补充具体日志) | 故障注入方法(和测试对齐) | 严酷度 | 恢复 | 现有改进需求 | 新增改进需求 | 维度 | 备注(beta单、问题单) | 刷新责任人 | | ||
| 34 | +| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | | ||
| 35 | +| distributed_flow_control.cpp:36 | KvManagerFlowControl | I-16 消息过载/流控失效 | **代码bug**:第36行`size_t listSize = kvStoreTimestampList_.size()`应为`kvDataManagerTimestampList_.size()`。复制粘贴错误导致KvManager流控检查了错误的列表→流控误拒绝或失效 | 流控失效→高频KvManager调用不受限→分布式数据库服务端过载→IPC线程池打满→正常客户端连锁超时→分布式通知业务大面积卡顿 | 流控拒绝日志;KvManager调用频率统计 | 高频调用KvManager接口观察流控行为 | I | 无 | 有流控框架设计(双维度)但实现有bug | 将第36行kvStoreTimestampList_改为kvDataManagerTimestampList_ | 网络/数据 | 可直接修复的编码缺陷 | - | | ||
| 36 | +| notification_dialog.cpp:59 | StartEnableNotificationDialogAbility | P-03b 线程挂死 | IPC处理线程中执行`std::this_thread::sleep_for(200ms)`。innerLake==true且应用不在前台时阻塞IPC线程 | IPC线程被sleep阻塞200ms→该线程无法处理其他IPC→高并发场景IPC线程池吞吐量下降→通知服务响应延迟 | IPC调用耗时统计;线程堆栈停在sleep_for | 构造应用不在前台场景触发EnableNotificationDialog | II | 系统层(看门狗) | 无 | 移除sleep_for,改用异步定时器延迟检查;或条件变量带超时等待前台状态变更 | 进程/线程 | 代码证据明确 | - | | ||
| 37 | +| notification_subscriber_manager.cpp:586-609; notification_local_live_view_subscriber_manager.cpp:164-184 | OnRemoteDied(submit_h+wait阻塞) | P-03b 线程挂死 / I-08 回调注册泄漏 | OnRemoteDied从Death Recipient回调线程调用,内部submit_h+wait**阻塞等待**。队列中已有大量任务或当前任务执行同步IPC到已死亡订阅者时wait长时间阻塞。还调用RemoveSystemLiveViewNotificationsOfSa可能向notificationSvrQueue_提交形成跨队列依赖 | Death Recipient线程阻塞→死亡订阅者record未及时清理→subscriberRecordList_积累已死亡订阅者→后续NotifyConsumed对已死亡订阅者发起IPC→IPC超时→恶性循环→通知分发延迟→服务卡死 | 队列深度dump;Death Recipient线程堆栈停在wait;通知分发延迟监控 | 通知风暴场景注入订阅者进程死亡,观察Death Recipient线程阻塞时长 | II | 无 | 无 | OnRemoteDied改用submit(不等待)异步清理;为wait增加超时;避免跨队列调用 | 线程/接口 | 双路径交叉验证命中 | - | | ||
| 38 | +| distributed_rdb_helper.cpp:153-167,189-206,228-238,274-283 | InsertData/InsertBatchData/DeleteData/QueryData | T-02 死锁 / D-03 事务未回滚 | 持rdbStorePtrMutex_期间执行InsertWithConflictResolution/BatchInsert/Delete/Query等DB操作。磁盘IO慢/大数据量/WAL锁竞争时阻塞。InsertBatchData未包显式事务 | DB操作慢→rdbStorePtrMutex_长期持有→其他DB操作排队→分布式偏好查询/写入阻塞→通知图标同步/偏好设置中断 | DB操作耗时统计;rdbStorePtrMutex_等待时间;WAL锁日志 | 大数据量写入压测;构造磁盘IO慢场景 | II | 代码层(E_SQLITE_CORRUPT检测+RecoverDatabase+isRecovering_) | 有数据库损坏检测与自动恢复;ResultSet异常路径正确Close | 获取rdbStore_指针shared_ptr拷贝后释放锁再操作;InsertBatchData包显式事务;增加DB操作超时监控 | 数据/线程 | 单路径命中但证据明确 | - | | ||
| 39 | +| distributed_operation_connection.cpp:51 | OnAbilityConnectDone→SendRequest | P-04a Binder通信超时 | `remoteObject->SendRequest(EVENT_CALL_NOTIFY,...)`使用默认MessageOption(TF_SYNC)无超时设置。对端Ability处理慢或死锁时阻塞 | 对端Ability卡死→SendRequest阻塞→连接回调线程挂起→后续Ability连接回调排队→分布式通知回复操作中断 | Binder调用超时日志;连接回调线程堆栈 | 对端Ability注入死循环后触发连接 | II | 系统层(Binder默认超时5s) | 无 | 设置MessageOption超时(SetWaitTime);或改用异步IPC | 网络 | 单路径命中 | - | | ||
| 40 | +| notification_rdb_data_mgr.cpp:373-394,93-115 | InitCreatedTables / GetTableNames | D-04 查询结果集未关闭 | absSharedResultSet在GoToFirstRow失败时和GetString失败时直接返回未调用Close()。GetTableNames中所有路径均未Close() | ResultSet泄漏→反复重启累积→RDB连接/内存资源耗尽→所有DB操作失败 | fd/内存统计;RDB连接数监控 | 反复触发DB异常路径,观察ResultSet泄漏 | II | 无 | 无 | 使用RAII或scope guard确保所有return路径调用Close() | 数据/内存 | 双路径交叉验证命中 | - | | ||
| 41 | +| notification_rdb_data_mgr.cpp:1117-1151 | GetUserTableName | T-03 数据竞争 | createdTables_第一次检查(无锁)读取std::set,双重检查锁定模式(DCLP)对非原子变量不安全 | 并发创建用户表时无锁读取→读到不一致状态→重复创建表或漏创建→后续操作错误 | TSA报告;表创建异常日志 | 并发调用GetUserTableName创建不同用户表 | II | 代码层(第二次检查有锁) | 第二次检查在createdTableMutex_保护下 | 移除第一次无锁检查直接加锁;或用std::shared_mutex读写锁 | 线程 | 单路径命中 | - | | ||
| 42 | +| notification_rdb_data_mgr.cpp:357-368 | Init(第二次GetRdbStore) | I-03 返回值未完整处理 | 第一次GetRdbStore返回E_SQLITE_CORRUPT后删除重试,第二次只检查rdbStore_==nullptr未检查ret值。返回非E_OK但rdbStore_非null时使用不健康DB | 使用不健康DB对象→后续操作崩溃或数据损坏 | DB操作错误日志;GetRdbStore返回值日志 | 构造DB文件部分损坏场景 | II | 无 | 无 | 第二次GetRdbStore后同时检查ret和rdbStore_ | 接口/数据 | 单路径命中 | - | | ||
| 43 | +| notification_clone_manager.cpp:319-338 | SaveConfig | I-03 返回值未完整处理 / F-01a | fwrite返回值不等于config.length()时只记录日志不返回错误,继续执行fflush/fsync/fclose。不完整数据被当作成功 | 磁盘空间不足/IO错误时部分写入→不完整配置被备份→换机克隆恢复不完整→通知偏好丢失 | 文件大小校验;备份恢复测试 | 构造磁盘满场景触发SaveConfig | II | 代码层(有fsync) | 有fflush/fsync确保落盘 | fwrite返回值不匹配时返回错误,不继续后续操作 | 数据/接口 | 单路径命中 | - | | ||
| 44 | +| notification_subscriber_manager.cpp:802等13处; 1772 | NotifyConsumedInner/GetSubscriberRecords等(subscriberRecordList_无锁遍历) | T-03 数据竞争 | 13+函数遍历subscriberRecordList_未持subscriberRecordListMutex_,依赖notificationSubQueue_串行化但GetSubscriberRecords直接返回副本无锁 | 绕过队列调用时遍历期间修改→迭代器失效→崩溃 | faultlog崩溃栈;TSA报告 | 绕过队列直接调用GetSubscriberRecords同时触发订阅者注册 | II | 模块层(notificationSubQueue_串行化) | 部分函数(GetIsEnableEffectedRemind等)已加锁 | 所有遍历函数统一加锁;GetSubscriberRecords必须加锁 | 线程 | 单路径命中,置信度中 | - | | ||
| 45 | +| snooze_delay_manager.cpp:259-275,341-350 | TriggerSnoozeDelay/CheckSnoozeTimer | T-03 数据竞争 / T-02 死锁 | TriggerSnoozeDelay持snoozeNotificationMutex_循环体内调用SetEncryptToDB(加密+DB写)。RemoveAllFromSnoozeDelayList持锁调用DeleteSnoozeNotificationFromDB。CheckSnoozeTimer无锁访问snoozeDelayTimerList_ | 持锁DB IO阻塞→snoozeNotificationMutex_长期持有→所有snooze操作阻塞;或无锁读取并发修改→崩溃 | DB操作耗时统计;锁等待时间 | 高频触发snooze延迟通知同时检查定时器 | II | 无 | 无 | 锁内收集record列表拷贝,释放锁后执行DB操作;CheckSnoozeTimer加锁 | 线程/数据 | 双路径交叉验证命中 | - | | ||
| 46 | +| distributed_database.cpp(整体) | DistributedDatabase(未注册KvStore死亡通知) | I-01 对端进程死亡 | 注册了DeviceManager的OnRemoteDied但**未注册KvStore/KvDataManager死亡通知**。kvstore服务死亡后kvStore_指针可能无效,后续Put/Get崩溃或静默失败 | KvStore服务死亡→kvStore_失效→后续操作崩溃或失败→分布式通知同步中断 | 分布式同步失败日志;faultlog崩溃栈 | kill kvstore服务进程后触发分布式同步 | II | 无 | 有RecreateDistributedDB恢复接口(触发路径不明确) | 注册KvStore死亡通知;死亡回调中清理kvStore_并触发重建 | 网络/进程 | 单路径命中,置信度中 | - | | ||
| 47 | +| extension_service_connection.cpp:196-241 | OnAbilityConnectDone(持锁遍历+同步IPC) | I-09 嵌套同步IPC死锁 / T-02 死锁 | 持mutex_遍历messages_缓存队列调用NotifyOnReceiveMessage→proxy_->OnReceiveMessage同步IPC。形成OnAbilityConnectDone(锁)→Notify(重入锁)→proxy IPC调用链。IPC阻塞时mutex_长期持有 | proxy IPC阻塞→mutex_长期持有→连接管理全部阻塞→扩展订阅功能中断 | 连接管理线程堆栈;IPC调用耗时 | 对端ExtensionAbility注入死锁后触发连接 | II | 代码层(weakptr模式+recursive_mutex) | weakptr模式(wptr wThis);状态机检查 | 拷贝messages_后释放锁逐个处理;死亡回调中异步提交Close | 线程/网络 | 单路径命中 | - | | ||
| 48 | +| notification_timer_info.cpp:40-52 | OnTrigger | T-03 数据竞争 | OnTrigger中检查callBack_!=nullptr并调用callBack_()时**未持callBackMutex_**。定时器线程触发,SetCallbackInfo可能在其他线程执行 | 定时器触发时另一线程设置回调→读到部分写入的std::function→崩溃 | faultlog崩溃栈落在std::function调用 | 并发SetCallbackInfo和OnTrigger | III | 代码层(callBackMutex_存在但OnTrigger未使用) | SetCallbackInfo/GetCallBack有锁 | OnTrigger中使用GetCallBack()获取回调(有锁) | 线程 | 单路径命中 | - | | ||
| 49 | +| notification_liveview_utils.cpp:34-46; advanced_datashare_helper.cpp:250-261; advanced_notification_flow_control_service.cpp:74-97 | checkData/dataShareItems_/callerFlowControllerMapper_(无上限容器) | M-05 内存水位失控 | 多个无容量上限的容器:checkData(unordered_map)、dataShareItems_(vector)、callerFlowControllerMapper_(map per-uid list)。长期运行持续累积 | 容器持续增长→进程内存缓慢增长→长期运行后OOM→进程被系统杀死 | HiAppEvent资源泄漏事件;hidumper内存采样 | 长时间运行(24h+)后检查PSS增长 | III | 无 | flow_control有RemoveExpired清理 | 设置容量上限/LRU淘汰/定期清理 | 内存 | 单路径命中,置信度中 | - | | ||
| 50 | +| distributed_socket.cpp:191-200 | ClientBind(重试逻辑) | I-14 消息无响应 | BIND_SERVICE_MAX_RETRY_TIMES=1且BIND_SERVICE_SLEEP_TIMES_MS=10000已定义但**未使用**。重试循环while(retryTimes<1)只尝试一次。注释说"retry 10 times"实际1次。Bind本身可能阻塞无超时 | Bind失败→无重试→socket建立失败→该设备通知同步中断 | Bind失败日志;分布式同步成功率 | 构造瞬时网络问题导致Bind失败 | III | 代码层(有错误日志和AnalyticsUtil上报) | 有QoS参数;GetSocketId下次调用重新Bind | 增加重试次数(如3次)与退避;修正注释;为Bind增加超时 | 网络 | 单路径命中 | - | | ||
| 51 | +| advanced_notification_publish_service.cpp:919-1009 | DuplicateMsgControl/uniqueKeyList_等 | T-03 数据竞争 | uniqueKeyList_/distributedUniqueKeyList_/localUniqueKeyList_三个list无独立锁,依赖notificationSvrQueue_串行化。IsDuplicateMsg接收const list&引用,遍历期间若另一线程修改→迭代器失效 | 绕过队列调用→迭代器失效→崩溃 | faultlog崩溃栈;TSA报告 | 绕过队列直接调用DuplicateMsgControl同时发布通知 | III | 模块层(notificationSvrQueue_串行化) | 所有当前调用点在队列中 | 为三个列表添加独立锁或明确标注"必须在队列中调用" | 线程 | 单路径命中,置信度低 | - | | ||
| 52 | +| snooze_delay_manager.cpp:341-350 | CheckSnoozeTimer(无锁访问snoozeDelayTimerList_) | T-03 数据竞争 | CheckSnoozeTimer直接访问snoozeDelayTimerList_.empty()和StartSnoozeTimer()不持snoozeNotificationMutex_,可能与其他持锁修改列表的函数并发 | 无锁读取时并发修改→数据竞争→未定义行为→潜在崩溃 | TSA报告 | 并发触发CheckSnoozeTimer和InsertSnoozeDelayTimer | III | 无 | 无 | CheckSnoozeTimer中加锁保护 | 线程 | 单路径命中,置信度中 | - | | ||
| 53 | + | ||
| 54 | +--- | ||
| 55 | + | ||
| 56 | +## 置信度评估 | ||
| 57 | + | ||
| 58 | +- **整体置信度**: **中-高** | ||
| 59 | +- **输入质量**: | ||
| 60 | + - 代码完整可读(services/ans 334文件 + services/distributed 155文件 + domain/infrastructure 88文件) | ||
| 61 | + - 故障模式库已加载(内置扩展版,11大类60+故障模式) | ||
| 62 | + - 可靠性目标描述清晰(4个目标) | ||
| 63 | +- **执行过程**: | ||
| 64 | + - 双路径覆盖:自上而下从"服务卡死/OOM/业务中断"目标推导判据,聚焦锁使用密集函数、IPC调用链、持久化路径;自下而上全库检索高风险构造(锁/IPC/DeathRecipient/RDB/softbus/while/sleep) | ||
| 65 | + - 3个subagent并行分析3个独立区域(ANS核心服务锁并发、分布式通信持久化、ANS持久化发布订阅) | ||
| 66 | + - 传播链完整:每个风险点均含从代码构造到失效表现的完整链路 | ||
| 67 | + - 防护措施识别覆盖:每个风险点均标注防护层级 | ||
| 68 | +- **输出检查**: | ||
| 69 | + - 风险点均含位置/根因/传播/严重度/防护措施/建议 | ||
| 70 | + - **双路径交叉验证命中**(高置信): | ||
| 71 | + - 持锁期间同步IPC:3个subagent均命中(13+处实例)→ 系统性设计缺陷 | ||
| 72 | + - notificationList_无锁数据竞争:Subagent1三次从不同角度确认 → 高置信 | ||
| 73 | + - OnRemoteDied空实现/不安全:Subagent1+2+3均命中 → 高置信 | ||
| 74 | + - RecoverDatabase竞态窗口:Subagent3两个角度确认 → 高置信 | ||
| 75 | + - snooze_delay_manager持锁DB:Subagent1+3交叉命中 → 高置信 | ||
| 76 | + - 单路径命中(中/低置信):流控bug、GetDeviceList返回引用、serverSocket_无锁等 | ||
| 77 | + | ||
| 78 | +--- | ||
| 79 | + | ||
| 80 | +## 待进一步验证项(推理风险,建议动态验证) | ||
| 81 | + | ||
| 82 | +1. **notificationList_并发场景**:构造高频发布通知+同时dump查询GetAllNotification,观察是否触发崩溃(风险点1/D级) | ||
| 83 | +2. **持锁IPC阻塞实测**:对端服务注入死循环/sleep后测量锁等待时长和IPC线程池耗尽时间(风险点2/D级,系统性) | ||
| 84 | +3. **::SendMessage实际阻塞行为**:确认软总线接口是否内部有超时机制(风险点4/D级) | ||
| 85 | +4. **OnRemoteDied空实现影响**:kill DeviceManager服务后触发分布式通知同步,验证是否静默失败(风险点3/D级) | ||
| 86 | +5. **流控bug影响范围**:高频调用KvManager接口验证流控是否失效(风险点1/C级) | ||
| 87 | +6. **RecoverDatabase竞态窗口**:并发触发E_SQLITE_CORRUPT后的InsertData,验证是否崩溃(风险点9/D级) | ||
| 88 | +7. **RDB BatchInsert是否内部使用事务**:需确认RDB框架实现(风险点8/D级) | ||
| 89 | +8. **packageCached_队列内存增长**:高频发布通知(>1000条/秒)压测,验证OOM触发条件(风险点5/D级) | ||
| 90 | + | ||
| 91 | +--- | ||
| 92 | + | ||
| 93 | +## 优先处理建议 | ||
| 94 | + | ||
| 95 | +| 优先级 | 风险点 | 严酷度 | 类型 | 理由 | | ||
| 96 | +|---|---|---|---|---| | ||
| 97 | +| P0 | 持锁期间同步IPC(13+处) | I | D级 | 系统性设计缺陷,双路径交叉验证命中,最高卡死风险 | | ||
| 98 | +| P0 | notificationList_无锁并发访问 | I | D级 | 核心数据结构无锁,三路径交叉验证,崩溃风险 | | ||
| 99 | +| P0 | 分布式死亡回调空实现 | I | D级 | 静默失效无恢复,双路径交叉验证 | | ||
| 100 | +| P1 | 流控实现bug(kvStoreTimestampList_) | I | C级 | 可直接修复的编码缺陷,影响流控有效性 | | ||
| 101 | +| P1 | onCorruption无备份删除数据库 | I | D级 | 数据丢失不可恢复,高危操作 | | ||
| 102 | +| P1 | 软总线SendMessage无超时 | I | D级 | 永久挂起风险,传播链完整 | | ||
| 103 | +| P1 | packageCached_无界队列 | I | D级 | OOM风险,逻辑明确 | | ||
| 104 | +| P1 | GetDeviceList返回引用 | I | D级 | 数据竞争崩溃风险,代码证据明确 | | ||
| 105 | +| P2 | RDB无事务保护 | II | D级 | 掉电数据不一致,全文件无事务 | | ||
| 106 | +| P2 | RecoverDatabase竞态窗口 | II | D级 | 双路径交叉验证,崩溃风险 | | ||
| 107 | +| P2 | OnRemoteDied submit_h+wait阻塞 | II | C级 | 双路径交叉验证,通知分发延迟 | | ||
| 108 | +| P2 | RDB ResultSet未关闭 | II | C级 | 资源泄漏,双路径交叉验证 | | ||
| 109 | + | ||
| 110 | +--- | ||
| 111 | + | ||
| 112 | +## 三、依赖模块故障传播分析 | ||
| 113 | + | ||
| 114 | +分析 ANS 服务依赖的外部模块发生故障(进程崩溃/卡死/响应慢/未启动)时,故障如何传播到 ANS 服务并导致失效。 | ||
| 115 | + | ||
| 116 | +### 依赖模块清单 | ||
| 117 | + | ||
| 118 | +| 依赖模块 | 关键故障模式 | 调用方式 | 调用点 | 当前通知现有的防护机制 | 重要程度 | | ||
| 119 | +|---|---|---|---|---|---| | ||
| 120 | +| BundleManagerService (BMS) | 依赖服务卡死→持锁IPC→线程池耗尽 | 持 connectionMutex_ → Connect() → 同步 IPC | GetBundleNameByUid/IsSystemApp/GetAllBundleOption/GetDefaultUidByBundleName/GetBundleInfo 等(20+处) | DeathRecipient(OnRemoteDied→Disconnect);Connect()懒重连;null检查返回默认值 | P0 | | ||
| 121 | +| DataShareService | 服务不可用→缓存过期→DND配置错误 | CreateDataShareHelper → Query/Update/Insert | DND 配置查询、联系人查询、智能场景查询(advanced_datashare_helper.cpp) | null检查;缓存机制(dataShareItems_);Observer注册更新缓存 | P2 | | ||
| 122 | +| AppMgrService | 依赖服务卡死→持锁IPC→观察者管理阻塞 | DelayedSingleton<AppMgrClient>→Register/Unregister | AddAppObserver/RemoveAppObserver(advanced_notification_utils.cpp:2629,2660) | 返回值检查;AddAppObserver注册IPC不持锁 | P1 | | ||
| 123 | +| OsAccountManager | 帐号服务失败→userId=-1传播→跨用户数据混淆 | OsAccountManagerHelper/直接 SDK 调用 | 偏好数据库中 30+处获取 userId | 部分函数检查userId==SUBSCRIBE_USER_INIT(约5处);Helper封装类有HA告警(被绕过) | P1 | | ||
| 124 | +| CommonEventService (CES) | 事件服务卡死→同步Publish→调用线程阻塞 | CommonEventManager::PublishCommonEvent | PublishSlotChangeCommonEvent(slot_service.cpp:1462) | 返回值检查并记录日志(失败不影响业务结果) | P1 | | ||
| 125 | +| AccessToken | 权限服务不可用→fail-closed全量拒绝→功能瘫痪 | AccessTokenHelper 封装 | 几乎所有 IPC 入口的权限校验 | AccessTokenHelper统一封装调用入口;fail-closed安全策略 | P0 | | ||
| 126 | +| DeviceManager | 依赖服务崩溃→死亡回调空实现→代理悬垂→静默失效 | DeviceManager::GetInstance().InitDeviceManager 等 | 分布式数据库初始化、设备列表获取(distributed_database.cpp) | OnRemoteDied注册但**空实现**;CheckKvDataManager null检查(失效) | P0 | | ||
| 127 | +| DistributedKvStore | 服务崩溃→未注册死亡通知→悬垂指针→崩溃 | kvDataManager_->GetSingleKvStore/Put/Get/Delete | 分布式通知发布/删除/查询全链路 | 流控(有bug);CheckKvStore懒初始化;GetEntries失败时reset | P1 | | ||
| 128 | +| SoftBus | 通信服务卡死→无超时socket→线程永久阻塞→OOM | ::SendMessage/::SendBytes/::Bind/::Shutdown | 分布式通知发送全链路(distributed_socket.cpp) | ffrt::submit异步化;OnClientShutdown回调标记socketId=-1;GetSocketId懒重连 | P0 | | ||
| 129 | +| AbilityManagerService | 依赖服务卡死→持锁IPC→通知跳转/扩展阻塞5s | AbilityManagerClient→StartAbility/ConnectAbility | 分布式通知跳转、扩展订阅连接(5+处) | 返回值检查;状态机检查(CREATED/CONNECTING/CONNECTED);消息缓存机制 | P1 | | ||
| 130 | +| ScreenLockManager | 服务不可用→默认返回false→锁屏时错误执行跳转 | ScreenLockManager::GetInstance()->IsScreenLocked/Unlock | 分布式通知操作时检查屏幕状态(3+处) | 无(#ifdef 条件编译,禁用时默认SCREEN_ON) | P1 | | ||
| 131 | +| TimeService | 服务不可用→定时器创建静默失败→资源泄漏 | TimeServiceClient->CreateTimer/StartTimer/StopTimer | 分布式解锁延迟任务(distributed_unlock_listener_oper_service.cpp) | 30s超时定时器(OPERATION_TIMEOUT);null检查 | P1 | | ||
| 132 | +| SystemAbilityManager (SAMGR) | 服务不可用→代理永久为null→功能降级 | GetSystemAbilityManager->GetSystemAbility | 获取各种系统服务代理 | null检查返回默认值(不崩溃但功能降级) | P2 | | ||
| 133 | + | ||
| 134 | +--- | ||
| 135 | + | ||
| 136 | +### 架构与设计问题(D级)— 依赖模块故障传播 | ||
| 137 | + | ||
| 138 | +> **新增列说明**: | ||
| 139 | +> - **关键故障模式**:故障从依赖模块传播到 ANS 失效的精炼模式名,便于快速理解故障本质 | ||
| 140 | +> - **当前通知现有的防护机制**:ANS 服务自身(非依赖模块)已实施的针对该故障的防护措施 | ||
| 141 | +> - **重要程度**:综合严酷度、可能性、影响范围得出的优先级(P0 最高→P3 最低) | ||
| 142 | + | ||
| 143 | +| 分析对象 | 分析子对象 | 失效模式 | 关键故障模式 | 失效原因 | 失效影响 | 定位方法 | 故障注入方法 | 严酷度 | 重要程度 | 恢复 | 当前通知现有的防护机制 | 现有改进需求 | 新增改进需求 | 维度 | 备注 | 刷新责任人 | | ||
| 144 | +|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---| | ||
| 145 | +| bundle_manager_helper.cpp:58-68 等 20+处 | GetBundleNameByUid 等持锁 IPC | I-02 IPC调用阻塞 | 依赖服务卡死→持锁IPC→锁无法释放→IPC线程池耗尽 | 所有 BMS 调用持 connectionMutex_ 期间发起同步 IPC,无超时。BMS 卡死时锁被长期持有 | BMS 卡死→ANS 线程在 connectionMutex_ 上排队→所有需要 BMS 的通知操作阻塞→IPC 线程池耗尽→ANS 服务瘫痪 | THREAD_BLOCK watchdog 事件;ANR trace;IPC 调用耗时统计 | 注入 BMS 主线程死循环/sleep;慢设备压测 | I | P0 | 系统层(DeathRecipient 仅对崩溃有效,卡死无效) | Connect()每次调用懒重连;bundleMgr_为null时返回默认值(空字符串/-1/false)使功能降级而非崩溃;DeathRecipient监听BMS崩溃 | null 检查返回默认值;OnRemoteDied 有清理 | 持锁改无锁代理模式(锁内获取引用后释放锁再 IPC);IPC 添加超时;OnRemoteDied 用 try_lock | 线程/进程/接口 | 与第一部分"持锁同步IPC"交叉验证命中 | - | | ||
| 146 | +| bundle_manager_helper.cpp:48-52 | OnRemoteDied 持锁 | T-02 死锁 | 死亡回调与持锁IPC线程互等→DeathRecipient无法执行清理 | OnRemoteDied 获取 connectionMutex_,若已有线程持锁等 IPC 则 DeathRecipient 回调也阻塞,无法及时清理 bundleMgr_ | BMS 崩溃后 OnRemoteDied 阻塞→bundleMgr_ 未及时清空→恢复窗口延长→后续调用使用失效代理 | DeathRecipient 回调延迟日志;锁等待 trace | 模拟 BMS 崩溃同时并发 BMS 调用 | I | P0 | 系统层 | DeathRecipient注册(能监听崩溃);Disconnect()清理代理对象 | DeathRecipient 存在 | OnRemoteDied 用独立无锁路径清理(try_lock 或 atomic flag) | 线程 | 推理风险 | - | | ||
| 147 | +| access_token_helper.cpp:35-40 | VerifyCallerPermission 默认拒绝 | API-06 服务不可用降级缺失 | 权限服务不可用→fail-closed全量拒绝→功能瘫痪 | AccessToken 服务不可用时所有权限校验返回 false(默认拒绝/fail-closed) | 所有通知发布被拒绝;系统应用调用被拒绝;SA 调用被拒绝→ANS 功能完全瘫痪 | AccessToken 服务状态监控;权限拒绝事件统计 | kill AccessToken 服务进程 | I | P0 | 系统层(服务恢复后自动恢复) | 无降级机制(fail-closed安全侧正确但可用性灾难);AccessTokenHelper封装统一了调用入口但未做服务不可用降级 | fail-closed 安全侧正确 | 关键系统应用权限缓存决策;区分服务不可用与权限拒绝 | 接口/进程 | 推理风险 | - | | ||
| 148 | +| distributed_database.cpp:58 | DeviceInitCallBack::OnRemoteDied 空实现 | P-01 进程崩溃后代理悬垂 | 依赖服务崩溃→死亡回调空实现→代理悬垂→静默失效 | OnRemoteDied 仅打日志不清理 kvDataManager_/kvStore_。DeviceManager 死亡后 kvDataManager_ 仍非空,CheckKvDataManager 通过但底层连接已断 | DeviceManager 死亡→后续 GetSingleKvStore 等持续失败→分布式通知同步全链路静默失效→无上层通知无恢复 | HiAppEvent 分布式操作失败事件;日志搜索"OnRemoteDied called" | kill DeviceManager 进程后触发分布式通知发布 | I | P0 | 无 | CheckKvDataManager()null检查(因指针非null形同虚设);KvStoreFlowControl流控(有bug);GetSingleKvStore返回值检查 | CheckKvDataManager null 检查(因指针非 null 形同虚设) | OnRemoteDied 中清理 kvDataManager_/kvStore_+通知上层+延迟重连 | 进程 | 与第一部分交叉验证命中 | - | | ||
| 149 | +| distributed_socket.cpp:226 | ClientSendMessage→::SendMessage 无超时 | P-05a Socket 阻塞 / I-14 消息无响应 | 通信服务卡死→无超时socket调用→线程永久阻塞→队列积压→OOM | 软总线 ::SendMessage/::SendBytes 无超时保护,SoftBus 卡死时调用线程永久挂起 | SoftBus 卡死→发送线程永久阻塞→ffrt 线程池被占用→packageCached_ 队列积压→内存增长→OOM | THREAD_BLOCK 事件;调用线程堆栈停在 ::SendMessage | 注入 SoftBus 死循环;断开网络后触发发送 | I | P0 | 系统层(软总线底层可能有部分超时) | ffrt::submit异步化发送(不阻塞主流程);OnClientShutdown回调标记socketId=-1;GetSocketId懒重连触发重新Bind | ffrt::submit 异步化 | 为 ::SendMessage 增加超时包装;packageCached_ 设上限 | 网络/线程 | 与第一部分交叉验证命中 | - | | ||
| 150 | +| advanced_notification_slot_service.cpp:1462 | PublishSlotChangeCommonEvent 同步调用 | I-02 IPC调用阻塞 | 事件服务卡死→同步PublishCommonEvent→调用线程阻塞 | PublishCommonEvent 同步调用,CES 卡死时阻塞调用线程。该函数在 Slot 更新/通知发布流程中 | CES 卡死→Slot 更新/通知发布流程的 IPC 线程阻塞→ANS 线程池逐步耗尽 | IPC 调用耗时统计;ANR trace | 注入 CES 主线程死循环 | II | P1 | 无 | 返回值检查并记录日志(PublishCommonEvent失败仅日志不影响业务结果) | 返回值检查并记录日志 | 改为异步发布(独立 FFRT 任务);不阻塞业务流程 | 线程/接口 | 推理风险 | - | | ||
| 151 | +| advanced_notification_utils.cpp:2646-2661 | RemoveAppObserver 持锁 IPC | I-02 IPC调用阻塞 | 依赖服务卡死→持锁IPC→观察者管理阻塞→实况通知阻塞 | 持 appObserverLock_ 期间调用 UnregisterApplicationStateObserver(IPC) | AppMgr 卡死→appObserverLock_ 被持有→IsExistsPidInObservers 阻塞→实况通知发布阻塞 | THREAD_BLOCK 事件;全线程堆栈 | 注入 AppMgrService 主线程睡眠 | II | P1 | 无 | AddAppObserver注册IPC不持锁(仅Unregister持锁);返回值检查(ERR_OK) | AddAppObserver 注册 IPC 不持锁 | IPC 调用移到锁外 | 线程/接口 | 推理风险 | - | | ||
| 152 | +| distributed_unlock_listener_oper_service.cpp:105 | 持 mapLock_ 期间 StopTimer/DestroyTimer | I-02 IPC调用阻塞 | 时间服务卡死→持锁IPC→延迟任务管理阻塞 | 持 mapLock_ 期间调用 StopTimer/DestroyTimer(IPC) | TimeService 卡死→mapLock_ 持有 5s→延迟任务管理全部阻塞 | THREAD_BLOCK 事件 | 注入 TimeService 卡死 | II | P1 | 模块层(operationQueue 异步超时处理) | 30s超时定时器(OPERATION_TIMEOUT)防止任务永久挂起;operationQueue_异步执行超时处理 | 30s 超时定时器 | IPC 移出锁保护;先收集 timerId 解锁后 IPC | 线程/接口 | 推理风险 | - | | ||
| 153 | +| distributed_observer_service.cpp:107; distributed_operation_service.cpp:80 | IsScreenLocked 无错误处理 | I-11 接口返回失败未处理 | 屏幕锁服务不可用→默认返回false(未锁屏)→错误执行跳转 | ScreenLockManager 不可用时 IsScreenLocked 返回默认值 false(未锁屏),无降级策略 | 锁屏时错误执行跳转操作→跳转失败或行为异常 | 日志搜索 IsScreenLocked 调用 | kill ScreenLockManager 后触发操作 | II | P1 | 无 | #ifdef SCREENLOCK_MGR_ENABLE条件编译(禁用时默认SCREEN_ON) | #ifdef 条件编译 | 失败时默认 true(锁屏状态)走延迟路径;返回值检查 | 接口 | 推理风险 | - | | ||
| 154 | +| extension_service_connection.cpp:62 | 构造函数 CreateTimer 返回值未检查 | I-11 接口返回失败未处理 | 时间服务不可用→定时器创建静默失败→连接资源泄漏 | TimeService 不可用时 CreateTimer 返回 0,Freeze/Disconnect 定时器失效 | 连接资源泄漏;扩展进程不被冻结→功耗增加 | 内存监控连接数增长 | kill TimeService 后创建 ExtensionConnection | II | P1 | 代码层(null 检查) | null检查(TimeServiceClient==nullptr时return);FREEZE_PREPARE_TIME/DISCONNECT_DELAY_TIME延迟机制 | FREEZE_PREPARE_TIME 机制 | 检查 CreateTimer 返回值;失败时用 ffrt timer 备用 | 接口/内存 | 推理风险 | - | | ||
| 155 | + | ||
| 156 | +### 编码问题(C级)— 依赖模块故障传播 | ||
| 157 | + | ||
| 158 | +| 分析对象 | 分析子对象 | 失效模式 | 关键故障模式 | 失效原因 | 失效影响 | 定位方法 | 故障注入方法 | 严酷度 | 重要程度 | 恢复 | 当前通知现有的防护机制 | 现有改进需求 | 新增改进需求 | 维度 | 备注 | 刷新责任人 | | ||
| 159 | +|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---| | ||
| 160 | +| notification_preferences_database.cpp:402,526,554,857,957,1147,2314,2335,2739 等 15+处 | GetOsAccountLocalIdFromUid 无错误检查 | D-03 未校验返回值 | 帐号服务失败→userId=-1传播→DB写入错误分区→跨用户数据混淆 | userId=-1 未检查直接用于 DB 操作。OsAccountManager 失败时 userId 保持初始值-1 | 跨用户数据混淆:偏好写入 userId=-1 分区,其他用户查询无法命中 | DB 中 userId=-1 记录异常告警 | mock OsAccountManager 返回错误 | II | P1 | 无 | 部分函数检查userId==SUBSCRIBE_USER_INIT(约5处);OsAccountManagerHelper封装类有HA告警(但被绕过) | 部分函数检查 userId==SUBSCRIBE_USER_INIT | 统一封装强制检查 userId 有效性的辅助函数 | 数据/接口 | 推理风险 | - | | ||
| 161 | +| advanced_notification_publish.cpp:598; cancel.cpp:352,354,365,367; utils.cpp:1018 等 20+处 | 直接调用 OsAccountManager SDK 绕过 Helper | API-04 绕过封装层 | 绕过封装层→无错误日志→故障不可观测 | 直接 SDK 调用无返回值检查、无错误日志、无 HA 告警 | 故障不可观测;userId 错误设置到 request→通知关联到错误用户 | 日志中缺少 OsAccount 调用失败记录 | 对比 Helper 调用与直接调用的日志覆盖 | II | P1 | 无 | OsAccountManagerHelper封装类存在(提供HA告警和错误日志,但20+处未使用) | 无 | 全部替换为 OsAccountManagerHelper 封装调用 | 数据/接口 | 推理风险 | - | | ||
| 162 | +| bundle_manager_helper.cpp:182-183 | callingUserId 未初始化 | D-01 未初始化变量 | 未初始化变量→SDK失败时随机值→错误查询 | callingUserId 未初始化,OsAccountManager SDK 失败时为随机值传给 GetBundleInfoByBundleName | API 兼容性判断错误→通知发布流程分支选择错误 | 静态分析(未初始化变量扫描) | mock OsAccountManager 返回错误 | III | P2 | 无 | 无 | 无 | 初始化为-1 并检查返回值 | 数据 | 推理风险 | - | | ||
| 163 | +| advanced_notification_publish_service.cpp:734 | GetBundleNameByUid 返回空未检查 | D-03 未校验返回值 | 依赖服务崩溃→返回空值→空值传播到DB操作 | BMS 崩溃后返回空 bundleName,未检查就用于构造 NotificationBundleOption | DB 操作使用空 bundleName 作为 key→可能命中错误记录或写入空 key | DB 空 key 记录告警 | kill BMS 后触发通知发布 | II | P1 | 无 | smart_reminder_center.cpp:491有空值检查(部分调用点有,publish_service.cpp:734未检查) | smart_reminder_center.cpp:491 有检查 | 添加空值检查,失败时返回错误 | 数据/接口 | 推理风险 | - | | ||
| 164 | +| advanced_notification_slot_service.cpp:1432 | 硬编码 userId=100 默认值 | D-05 硬编码默认值 | 默认值硬编码→服务失败时使用错误默认值继续 | GetCurrentActiveUserId 失败后使用 100 继续 | 查询到错误用户数据 | userId=100 异常告警 | mock GetCurrentActiveUserId 失败 | III | P2 | 无 | 带参版本有CheckUserExists检查(无参版本无检查) | 带参版本有 CheckUserExists | 失败时返回错误而非继续 | 数据 | 推理风险 | - | | ||
| 165 | +| advanced_datashare_helper.cpp:250-261 | 缓存无 TTL | D-06 缓存数据过期 | 缓存无过期→服务不可用时返回陈旧数据→DND策略错误 | dataShareItems_ 无 TTL,DataShare 不可用时返回过期值 | DND/焦点模式配置返回旧值→通知静默策略错误 | 配置一致性校验日志 | 修改 DataShare 配置后断开服务 | III | P2 | 模块层(Observer 更新缓存) | DataShare Observer注册(数据变更时更新缓存);QuerydataShareItems先查缓存减少IPC | Observer 注册 | 缓存项添加 TTL;服务恢复时刷新缓存 | 数据/接口 | 推理风险 | - | | ||
| 166 | +| distributed_unlock_listener_oper_service.cpp:60 | CreateTimer/StartTimer 返回值未检查 | I-11 接口返回失败未处理 | 接口返回失败未处理→任务静默入队→操作丢失 | TimeService 不可用时 CreateTimer 返回 0,但任务仍入队 | 延迟任务静默失败,锁屏期间通知操作丢失 | 日志搜索 CreateTimer 返回值 | kill TimeService 后 AddDelayTask | II | P1 | 代码层(null 检查) | null检查(TimeServiceClient==nullptr时return);OPERATION_TIMEOUT 30s超时兜底 | OPERATION_TIMEOUT | 检查返回值;失败不入队或用备用定时器 | 接口 | 推理风险 | - | | ||
| 167 | +| distributed_screen_status_manager.cpp:191 | CheckRemoteDevicesIsUsing reset 不完整 | P-01 数据悬垂 | 部分清理→kvStore_悬垂→后续操作崩溃 | GetTrustedDeviceList 失败后 reset kvDataManager_ 但不 reset kvStore_ | kvStore_ 可能悬垂→后续 GetEntries 崩溃 | crash 栈 | kill DeviceManager 后调用 CheckRemoteDevicesIsUsing | III | P2 | 代码层(懒恢复) | GetEntries失败时kvStore_.reset()(代码层懒恢复);CheckKvDataManager懒初始化 | null 检查 | 同时 reset kvStore_ | 进程/数据 | 推理风险 | - | | ||
| 168 | + | ||
| 169 | +### 级联故障场景 | ||
| 170 | + | ||
| 171 | +| 级联场景 | 关键故障模式 | 触发链路 | 放大效应 | 严酷度 | 重要程度 | 当前通知现有的防护机制 | 建议 | | ||
| 172 | +|---|---|---|---|---|---|---|---| | ||
| 173 | +| BMS + SAMGR 同时故障 | 多依赖同时不可用→多模块功能同时降级 | SAMGR 崩溃→BMS 代理不可用→bundleMgr_=null→同时影响 ExtensionServiceConnection::GetPid(GetSystemAbility(APP_MGR_SERVICE_ID) 也失败) | 分布式通知无法获取应用图标+扩展进程 PID 获取失败+Freeze/Unfreeze 无法精确控制 | II | P1 | null 检查返回默认值(不崩溃但功能降级) | 检测到 SAMGR 不可用时进入降级模式 | | ||
| 174 | +| DeviceManager + KvStore 同时故障 | 依赖服务崩溃→恢复路径被阻断→永久失效 | DM 崩溃→OnRemoteDied 空实现→kvDataManager_ 悬垂→GetSingleKvStore 失败→KvStore 死亡通知触发 RecreateDistributedDB→依赖悬垂的 kvDataManager_→DeleteKvStore 失败→**永久失效** | 双重故障表现为单一故障,DM 故障阻断 KvStore 恢复路径,无故障隔离 | I | P0 | 无(OnRemoteDied空实现导致无任何恢复) | OnRemoteDied 中清理 kvDataManager_;KvStore 恢复路径不依赖 DM | | ||
| 175 | +| SoftBus + TimeService 同时故障 | 故障掩盖→恢复后批量爆发 | SoftBus 故障→通知不发→对端不触发 HandleNotificationOperation→TimeService 延迟任务不创建→TimeService 故障影响被掩盖。SoftBus 恢复后批量通知发送→多个 AddDelayTask→TimeService 仍未恢复→批量操作丢失 | 故障被掩盖后批量爆发 | II | P1 | 30s 超时定时器(OPERATION_TIMEOUT)兜底 | 延迟任务创建失败时缓存操作信息,TimeService 恢复后重建 | | ||
| 176 | + | ||
| 177 | +--- | ||
| 178 | + | ||
| 179 | +### 依赖模块故障传播置信度评估 | ||
| 180 | + | ||
| 181 | +- **整体置信度**: **中-高** | ||
| 182 | +- **输入质量**: 代码完整可读,13 个依赖模块的调用路径、防护措施均已通过代码确认 | ||
| 183 | +- **执行过程**: 双路径覆盖;自上而下从 ANS 业务入口追踪到各依赖调用点;自下而上从代码构造(空回调/持锁IPC/无超时/无错误检查)推导失效表现;2 个 subagent 并行分析 ANS 核心依赖和分布式依赖 | ||
| 184 | +- **交叉验证命中**: BMS 持锁 IPC、DeviceManager OnRemoteDied 空实现、SoftBus SendMessage 无超时 等3个风险点与前次评审交叉验证命中 | ||
| 185 | +- **降级原因**: SoftBus `::SendMessage`/`::Shutdown` 的实际阻塞行为依赖 SoftBus 实现;ScreenLockManager `IsScreenLocked()` 失败返回值依赖客户端实现;TimeService `CreateTimer` 失败返回值未读取源码确认 | ||
| 186 | + | ||
| 187 | +### 待进一步验证项(依赖模块故障传播) | ||
| 188 | + | ||
| 189 | +1. **BMS IPC 默认超时值**: 需确认 OpenHarmony IPC 框架对 BMS 调用的默认超时(推测 5~15s),影响持锁阻塞时长 | ||
| 190 | +2. **OnRemoteDied 与持锁 IPC 的实际死锁可能性**: 需确认 IPC 超时返回后线程是否释放锁(lock_guard 析构时机),若 IPC 超时后调用返回则锁会释放 | ||
| 191 | +3. **OsAccountManager SDK 失败时 userId 输出参数行为**: 需确认 `GetOsAccountLocalIdFromUid` 失败时是否修改输出参数(推测不修改,保持初始值) | ||
| 192 | +4. **AccessToken 服务不可用时 VerifyAccessToken 的实际返回值**: 需确认 SDK 是否返回特定错误码 | ||
| 193 | +5. **SoftBus `::SendMessage` 在进程崩溃时是否阻塞**: 需读取 SoftBus 实现确认是返回错误码还是阻塞 | ||
| 194 | +6. **ScreenLockManager `IsScreenLocked()` 失败返回值**: 需读取客户端实现确认返回 false 还是抛异常 | ||
| 195 | +7. **`ANS_FEATURE_ORIGINAL_DISTRIBUTED` 与 `DISTRIBUTED_FEATURE_MASTER` 是否互斥**: 需确认实际产品配置 | ||
| 196 | + | ||
| 197 | +--- | ||
| 198 | + | ||
| 199 | +*评审完成(含依赖模块故障传播分析)。所有风险点均为基于代码构造的推理风险,非实测验证,建议通过故障注入测试进一步确认。* | ||