OpenHarmony电话子系统短信发送流程分析

发布时间:2026/7/9 5:16:14

OpenHarmony电话子系统短信发送流程分析 文档概述说明1.文章由移远通信技术股份有限公司提供2.以下内容包含了个人理解仅供参考如有不合理处请联系笔者修改概述OpenHarmony 的短信能力由 Telephony 子系统提供是标准系统的基础通信能力之一核心功能与相关说明如下1.‌核心系统能力‌支持短信/彩信暂不支持需要自行适配收发、SIM 卡短信管理、短信服务中心地址配置、默认 SIM 卡槽设置等基础能力配套提供了系统级 API 供开发者调用。2.‌应用侧开发能力‌系统预置短信应用已实现会话管理、消息收发、送达报告、短信备份、垃圾短信拦截等完整功能可通过一套代码适配手机、平板等多类设备。普通三方应用可通过 startAbility 接口拉起系统短信页面预填收件人与短信内容完成发送无需申请高权限系统短信 API。Flutter 生态已完成 flutter_sms 库适配支持短信对话框唤起、多收件人发送、设备短信能力检测等跨平台功能。架构设计分层模型短信发送模块采用四层架构自上而下分别为设计原则单一职责原则每个模块专注特定功能领域SmsSendManager发送调度与生命周期管理GsmSmsSender/CdmaSmsSender制式特定的编码与通信SmsNetworkPolicyManager网络路由与优先级决策策略模式应用网络制式差异通过策略对象动态封装运行时选择对应的Sender实例同一接口下适配多个网络标准异步处理模式所有发送操作均为异步非阻塞的事件驱动发送请求入队后立即返回通过回调机制通知应用层结果核心组件详解SmsInterfaceManager接口管理器职责范围对外提供统一的短信发送接口TextBasedSmsDelivery、DataBasedSmsDelivery管理每个 SIM 卡槽的资源生命周期请求的初步验证与权限检查核心方法int32_tTextBasedSmsDelivery(conststd::stringdesAddr,// 目标地址conststd::stringscAddr,// 短信服务中心地址conststd::stringtext,// 短信文本内容constsptrISendShortMessageCallbacksendCallback,// 发送结果回调constsptrIDeliveryShortMessageCallbackdeliveryCallback,// 送达报告回调int32_tid,// 业务标识符boolisMmsApptrue);// 是否为彩信应用关键特性接收来自应用程序的短信发送请求将请求转发给对应 SIM 卡槽的SmsSendManager与数据持久化层交互记录发送历史SmsSendManager发送管理器核心职责维护 GSM 和 CDMA 两种网络制式的发送器实例根据当前网络状态选择合适的发送路径实现发送队列与重试机制协调网络策略管理器的决策执行内部成员classSmsSendManager{private:int32_tslotId_;// SIM卡槽IDstd::shared_ptrSmsSendergsmSmsSender_;// GSM 发送器std::shared_ptrSmsSendercdmaSmsSender_;// CDMA 发送器std::shared_ptrSmsNetworkPolicyManagernetworkManager_;// 网络策略管理std::shared_ptrSmsShortCodeMatchersmsShortCodeMatcher_;// 短码匹配器};发送流程分类方法场景特点TextBasedSmsDelivery文本短信支持自动分段长短信打包发送DataBasedSmsDelivery数据短信指定端口号用于数据应用通信RetriedSmsDelivery重试短信发送失败后的自动重试机制SmsSender发送器基类设计特点采用模板方法模式的抽象基类classSmsSender:publicTelEventHandler{public:// 纯虚方法 - 子类必须实现virtualvoidTextBasedSmsDelivery(...)0;virtualvoidDataBasedSmsDelivery(...)0;virtualvoidSendSmsToRil(...)0;// 通用方法 - 所有Sender共享voidHandleMessageResponse(conststd::shared_ptrSmsSendIndexersmsIndexer);staticvoidSendResultCallBack(...);};职责分离基类定义通用流程请求排队、结果回调与重试调度子类实现制式特定功能PDU 编码、发送格式与参数配置GsmSmsSender 与 CdmaSmsSender两个子类基于相同的基类框架处理 GSM/CDMA 的特定编码与协议细节。GSM 短信特点使用 7-bit GSM 编码或 UCS2 编码PDU 格式定义明确严格按照 3GPP 规范支持长短信的分段与连接标识头Concatenation Header服务中心号码在PDU中显式指定CDMA短信特点使用8-bit编码消息参数采用TLVType-Length-Value格式多数参数可选需要区分实际值与默认值时间戳、优先级等参数独立传递SmsNetworkPolicyManager网络策略管理器职责定位根据当前网络状态决定短信应通过哪条网络路径传输。核心决策逻辑输入条件检查 ├─ 网络注册状态已注册/未注册 ├─ 域服务类型CS域/IMS域 ├─ 信号强度与连接质量 ├─ 用户配置的偏好设置 └─ 制式兼容性设备是否支持该制式 决策流程 1. 优先级评估 - IMS短信可用 → 选择IMS路径 - CS 域可用 → 选择对应制式GSM/CDMA - 都不可用 → 等待网络或返回错误 2. 队列管理 - 维护待发送队列 - 监听网络状态变化 - 状态好转时重新尝试发送参数决策表场景网络状态决策仅CS可用GSM 注册使用GSM通道仅CS可用CDMA 注册使用CDMA通道CS 与 IMS 均可用两者状态均良好IMS优先都不可用离线或无信号加入等待队列待网络恢复后重试短信发送流程完整发送链路应用层请求 │ ▼ SmsInterfaceManager::TextBasedSmsDelivery() │ 权限检查 ▶ 验证发送权限 │ 参数验证 ▶ 检查目标地址、内容有效性 │ ▼ SmsSendManager::TextBasedSmsDelivery() │ 分段处理 ▶ 长短信自动分段 │ 短码识别 ▶ 识别是否为短码安全检查 │ 网络路由 ▶ 调用SmsNetworkPolicyManager确定通道 │ ▼ SmsSender子类GsmSmsSender / CdmaSmsSender │ 编码转换 ▶ 文本转GSM 7-bit / UCS2 / CDMA编码 │ PDU生成 ▶ 构建完整的通信协议数据单元 │ 参数打包 ▶ 组装发送参数 │ ▼ SmsSendIndexer发送索引 │ 持久化存储 ▶ 记录到数据库支持失败重试 │ 队列入队 ▶ 加入发送队列 │ ▼ RIL层接口 │ 异步通信 ▶ 通过HDF通道向Modem下发AT命令 │ ▼ Modem硬件 │ 无线发送 ▶ 将短信通过无线信号传递 │ ▼ 回调处理链 │ 立即反馈 ▶ Modem返回发送状态成功/失败 │ 结果回调 ▶ 触发ISendShortMessageCallback回调 │ 送达报告 ▶ 网络返回送达确认时触发IDeliveryShortMessageCallback关键环节详解1. 分段处理Segmentation长短信长度超过单条限制需要自动分段处理。分段逻辑GSM 7-bit 编码单条最多 160 字符 → 超过自动分段UCS2 编码单条最多 70 字符 → 超过自动分段CDMA单条最多 200 字符 → 超过自动分段分段打包每条分段短信需添加连接标头UDH - User Data HeaderUDH 用于标明该分段在完整消息中的序号与总数接收端根据UDH重组为完整消息示例一条300字符的GSM短信被分为2段消息 这是一条300字符的短信... (300 chars) │ ├─ 分段1 [UDH标头] 消息1-157字符 │ (关键字段当前第1段总共2段) │ └─ 分段2 [UDH标头] 消息158-300字符 (关键字段当前第2段总共2段)2. 编码转换Encoding原始文本通过字符编码转换成 PDU 中的字节数据。GSM 7-bit 编码特点最常用的短信编码支持标准ASCII字符、数字、标点符号某些字符需要转义如[,],{,}编码后长度为原字符数UCS2 编码特点支持中文、日文、韩文等多语言字符每个字符占用2字节编码后长度为原字符数的两倍自动选择标准当文本中包含中文字符或其他非 GSM 7-bit 字符集支持的字符时采用 UCS2 编码编码选择算法if(contain_chinese||contain_unicode_char){encodingUCS2;max_per_message70;}elseif(can_encode_with_7bit){encodingGSM_7BIT;max_per_message160;}else{encodingUCS2;// 回退方案max_per_message70;}3. 网络路由决策Routing Decision系统需要根据实时网络状态决定通过哪条通道发送短信。决策点网络状态监听系统通过NetworkStateManager订阅网络变化事件网络从离线变为在线时启动待发队列的重试制式从 GSM 切换为 CDMA 时可能需要重新编码需缓存原始文本信号强度显著下降时延迟发送或增加重试次数4. 数据库持久化Persistence为支持发送失败后的重试机制系统在数据库中记录待发送的短信。SmsSendIndexer 数据结构持久化时机发送前确保即使进程崩溃数据也能恢复重试前更新重试次数和时间戳发送成功后标记为已完成可选删除5. 重试机制Retry Logic发送失败并非终点系统采用指数退避算法进行重试。重试策略重试触发条件网络状态恢复从无信号到有信号定时器触发指定延迟后自动重试通过后台服务定期扫描数据库中标记为“失败”的记录重试触发代码路径voidSmsSendManager::RetrySmsDelivery(conststd::shared_ptrSmsSendIndexersmsIndexer){// 从数据库读取原始消息// 重新走一遍编码、路由决策流程// 如果仍然失败增加retryCount// 再次计算延迟后重新调度}6. 回调通知机制Callback Notification异步操作完成后通过 Binder IPC 通知应用层结果。两类回调发送结果回调ISendShortMessageCallbackvoid OnSmsSendComplete(ISendShortMessageCallback::SmsSendResult result, // 成功/失败/缺少权限等std::string url // 可选的链接信息);触发时机Modem 返回发送结果通常在 0.5–2 秒内送达报告回调IDeliveryShortMessageCallbackvoid OnSmsDeliveryComplete(ISendShortMessageCallback::SmsSendResult result // 送达状态);触发时机网络返回送达确认可能延迟数秒至数分钟 **回调流程**Modem 返回 AT 响应│▼RIL 层解析响应│▼TelRilManager 回调 SmsSender::ProcessEvent()│▼SmsSender::HandleMessageResponse()│├─ 成功 → 调用 SendResultCallBack(resultSUCCESS)├─ 失败 → 调用 SendResultCallBack(resultFAILURE)│ 更新数据库状态为“失败”│ 如果 retryCount MAX调度重试│▼通过 Binder 通知应用的回调对象[短信中心号码长度] [短信中心号码][消息类型标志] [消息参考][目标地址长度] [目标地址类型] [目标地址][协议标识符] [数据编码方案][消息内容长度] [消息内容]**GsmSmsSender 实现职责** 1. 将目标号码和短信中心号码从国际格式转换为PDU格式 2. 选择合适的编码7-bit vs UCS2 3. 构建UDH如果需要分段 4. 调用RIL接口SendSms下发命令 ### CDMA制式短信 **编码特点** - 使用8-bit编码 - 消息结构为TLVTag-Length-Value格式 - 更复杂的可选参数 **消息体示例简化**[消息类型标签] [长度] [内容]├─ 消息参考可选├─ 目标地址├─ 原始消息体文本内容├─ 消息显示模式├─ 优先级└─ 回复选项可选**CdmaSmsSender实现职责** 1. 解析CDMA网络参数 2. 构建TLV格式的消息体 3. 填充可选参数 4. 调用RIL接口SendCdmaSms下发命令 ### 双卡场景处理 在支持双SIM的设备上系统需要为每张卡维护独立的发送管理器。 **架构设计** mermaid flowchart TD A[SmsService单例] -- B[SmsInterfaceManager (slotId0)] A -- C[SmsInterfaceManager (slotId1)] B -- D[SmsSendManager] D -- E[GsmSmsSender] D -- F[CdmaSmsSender] C -- G[SmsSendManager] G -- H[GsmSmsSender] G -- I[CdmaSmsSender]关键点发送操作需指定目标卡槽 ID不同卡槽的队列、重试计数完全独立网络状态监听需区分卡槽在支持双SIM的设备上系统需要为每张卡维护独立的发送管理器。架构设计SmsService单例 │ ├─ SmsInterfaceManager (slotId0) │ ├─ SmsSendManager │ │ ├─ GsmSmsSender │ │ └─ CdmaSmsSender │ └─ ... │ └─ SmsInterfaceManager (slotId1) ├─ SmsSendManager │ ├─ GsmSmsSender │ └─ CdmaSmsSender └─ ... **关键点** - 发送操作需指定目标卡槽 ID - 不同卡槽的队列、重试计数完全独立 - 网络状态监听需区分卡槽 ## 关键设计考量 ### 可靠性设计 **问题**短信发送失败会导致用户信息丢失。 **解决方案** 1. **持久化存储**发送前保存到数据库 2. **多次重试**采用指数退避策略 3. **网络监听**网络恢复时自动重试 4. **队列管理**维护内存队列以支持快速重试 **可靠性保证** - 在网络恢复后的 120 秒内99% 的失败短信可成功重试 - 发送失败后立即向用户返回结果避免其长时间等待 - 用户可在消息应用中查看重试历史 ### 性能优化 **问题**大量短信并发发送会导致系统响应延迟。 **解决方案** 1. **异步处理**采用非阻塞 I/O 操作 2. **队列限制**在内存中最多缓存1000条待发短信 3. **数据库批量操作**减少 I/O 次数 4. **编码缓存**避免重复的编码计算开销 **性能指标** - 单条短信从API调用到Modem响应 200ms - 1000条短信发送队列处理 10秒 ### 内存管理 **问题**长期运行中可能出现内存泄漏。 **设计考虑** 1. 使用智能指针std::shared_ptr、std::unique_ptr 2. 发送完成后及时释放缓存的PDU与编码数据 3. 定期清理已过期的重试记录 4. 对各类对象池设置容量上限 ### 安全性 **问题**防止非授权应用发送短信。 **实现方式** 1. **权限检查**检查应用是否持有SEND_MESSAGES权限 2. **短码识别**识别向短码常用于诈骗发送短信的行为 3. **频率限制**限制单应用的发送频率可选 4. **审计日志**记录所有短信发送操作 cpp // SmsSendManager中的权限检查示例 int32_t SmsSendManager::TextBasedSmsDelivery(...) { if (!CheckPermission(ISmsServiceInterface::SEND_MESSAGES)) { return PERMISSION_DENIED; } if (IsShortCode(desAddr)) { // 警告用户或拒绝发送 LogSecurityWarning(Attempt to send to short code: desAddr); } // ... 继续处理 }扩展性与可维护性添加新的网络制式要支持新的网络制式如5G 独立组网的短信需要创建新的Sender子类class NewNetworkSmsSender : public SmsSender {public:void TextBasedSmsDelivery(…) override;void DataBasedSmsDelivery(…) override;void SendSmsToRil(…) override;private:// 新制式特定的编码逻辑};注册到SmsSendManagervoid SmsSendManager::Init() {gsmSmsSender_ std::make_shared(…);cdmaSmsSender_ std::make_shared(…);newNetworkSender_ std::make_shared(…);}更新网络策略管理器// 在SmsNetworkPolicyManager中添加新制式的路由逻辑if (IsNewNetworkAvailable()) {return newNetworkSender_;}添加新的回调类型如果应用层需要新的回调信息如发送至哪个基站需执行以下步骤扩展回调接口interface ISendShortMessageCallback {void OnSmsSendComplete(SmsSendResult result,string url,string baseStationInfo // 新增字段);}在 SmsSender 中收集新信息void SmsSender::HandleMessageResponse(…) {// 从 Modem 响应中提取基站信息baseStationInfo ParseBaseStationFromModemResponse();// 传递给应用}监控与诊断系统通过以下指标进行健康度监控单小时发送成功率发送失败后的平均重试次数队列深度未发送的待发短信数从发起到完成的平均处理耗时诊断工具日志分析检索特定号码的发送记录状态导出功能导出当前发送队列状态模拟工具注入失败场景进行压力测试下面用 Mermaid 图展示四大设计考量之间的平衡关系保障兼顾支撑贯穿贯穿关键设计考量可靠性设计性能优化内存管理安全性持久化存储多次重试指数退避网络监听自动重试队列管理异步非阻塞 I/O队列上限 1000 条数据库批量操作编码缓存智能指针管理及时释放 PDU 缓存定期清理过期记录对象池容量上限权限检查 SEND_MESSAGES短码识别与告警频率限制审计日志总结OpenHarmony 的短信能力依托 Telephony 子系统构建是一套分层解耦、跨制式兼容的完整通信机制核心原理与运行逻辑可从以下维度展开说明一、底层基础机制短信本质是一种存储转发服务发送方的短信内容会先提交至短信服务中心暂存再由服务中心转发给目标接收方内容以文本、数字或二进制数据为主要载体。OpenHarmony 的短信模块作为系统常驻核心服务向下适配不同厂商的 Modem 硬件向上为应用层提供标准化的 JS API 接口同时兼容 GSM、CDMA 两大主流通信制式的短信协议规范。二、分层架构原理整个短信模块采用清晰的分层代码结构各层职责明确1.接口层‌对外暴露 JS 接口定义通过 Napi 完成 C 层与 JS 层的调用封装同时提供 Native 层内部调用接口2.框架层‌承载彩信编解码工具、短信业务通用处理逻辑实现跨硬件的能力抽象3.服务配置层‌提供 SystemAbility 启动配置文件确保短信服务随系统通信组件自动启动4.业务服务层‌包含 GSM、CDMA 制式专属的 PDU 编解码逻辑以及短信收发的核心业务处理代码5.工具层‌提供短信通用处理工具支撑长短信拆分、PDU数据解析等公共能力。三、短信发送全流程原理1.上层应用调用短信发送JS API经过Napi层将请求转发至Native层的SmsInterfaceManager对象2.SmsInterfaceManager完成参数合法性过滤、应用权限鉴权过滤无效请求3.请求转发至SmsSendManager调用搜网服务获取当前SIM卡状态与网络制式信息4.根据网络制式自动创建GsmSmsSender或CdmaSmsSender对长短信进行自动拆分将文本内容编码为符合协议规范的PDU数据包5.编码完成的短信加入发送队列通过RIL Adapter下发至底层Modem硬件最终提交至运营商短信服务中心6.若发送失败系统自动触发重发机制多次重试后将最终发送状态回调给上层应用。四、短信接收全流程原理1.系统启动时SmsReceiveManager会创建对应网络制式的短信接收处理器提前向RIL层注册短信事件监听2.运营商网络下发短信时Modem通过RIL Adapter将原始PDU数据上报至短信服务3.对应制式的接收处理器调用SmsBaseMessage组件完成PDU数据的解析还原出短信的发送方号码、内容、时间戳等核心信息4.系统自动完成短信存储、送达报告上报同时将短信通知分发至系统短信应用触发新消息提醒。五、配套扩展机制1.支持SIM卡内短信的增删改查管理可直接读写SIM卡存储的短信记录2.内置Wap Push接收处理、小区广播接收能力可处理运营商推送的特殊短信3.提供垃圾短信规则引擎支持自定义关键词、正则匹配规则自动拦截或标记垃圾短信4.跨平台适配层屏蔽硬件差异在RK3568等搭载4G模块的开发板上无需大幅修改代码即可完整实现短信收发全功能。

相关新闻