一、概述(卫星短信的特点与挑战)
Android 16 的卫星短信不使用传统 SmsDispatcher 路径,而是通过 SatelliteManager 的 Datagram(数据报)机制承载短信。这是一种完全独立的架构,与地面 SMS 走不同的代码路径。
核心特点:
- Datagram 承载:短信被编码为
SatelliteDatagram(byte[]),通过 sendDatagram() 发送,而非 SmsManager.sendTextMessage()
- 高延迟:卫星 RTT 500ms~数秒,Android 引入
SATELLITE_MODEM_STATE_DATAGRAM_RETRYING 状态处理重试
- 受限长度:
SatelliteCapabilities.maxBytesPerOutgoingDatagram 限制每条数据报最大字节数
- 需要指向:
isPointingRequired 标识是否需要用户对准卫星
- 存储转发:支持
pollPendingDatagrams() 主动拉取待接收消息
二、短信发送流程
分步骤
| 步骤 | 层级 | 动作 | 关键类/方法 |
|---|
| 1 | 应用层 | 短信App(如Messages)将短信编码为 SatelliteDatagram,调用 SatelliteManager.sendDatagram(DATAGRAM_TYPE_SMS, datagram, needFullScreenPointingUI, executor, resultListener) | SatelliteManager.java:2289 |
| 2 | API层 | sendDatagram() 通过 ITelephony.sendDatagram() 跨进程调用到 PhoneInterfaceManager | SatelliteManager.java:2307 |
| 3 | Telephony层 | PhoneInterfaceManager.sendDatagram() 委托给 SatelliteController.sendDatagram() | PhoneInterfaceManager.java:13043 |
| 4 | 控制层 | SatelliteController 将 datagram 通过 ISatelliteService.sendDatagram() 下发到卫星HAL服务 | SatelliteController (com.android.internal.telephony.satellite) |
| 5 | HAL层 | 卫星HAL服务通过HIDL/AIDL调用Modem,Modem将数据封装到卫星信令帧发送 | Vendor RIL / Satellite HAL |
| 6 | 链路层 | Modem完成卫星随机接入→数据帧发送→等待ACK | Modem firmware |
| 7 | 回调 | Modem返回结果→HAL回调→SatelliteController→PhoneInterfaceManager→IIntegerConsumer.accept(result)→应用 resultListener | 同上反向路径 |
时序图(Mermaid)
sequenceDiagram
participant App as 短信App
participant SM as SatelliteManager
participant PIM as PhoneInterfaceManager
participant SC as SatelliteController
participant HAL as SatelliteService(HAL)
participant Modem as Modem
App->>SM: sendDatagram(SMS, datagram, pointingUI, executor, listener)
SM->>PIM: ITelephony.sendDatagram(type, datagram, pointingUI, callback)
PIM->>SC: sendDatagram(type, datagram, pointingUI, callback)
SC->>SC: 检查modem状态(DATAGRAM_TRANSFERRING?)
SC->>HAL: ISatelliteService.sendDatagram()
HAL->>Modem: RIL/HAL命令
Modem->>Modem: 卫星随机接入+帧发送
alt 发送成功
Modem-->>HAL: 成功回调
HAL-->>SC: onDatagramSendResult(SUCCESS)
SC-->>PIM: callback.accept(SATELLITE_RESULT_SUCCESS)
PIM-->>SM: IIntegerConsumer.accept(0)
SM-->>App: resultListener.accept(SUCCESS)
else 发送失败需重试
Modem-->>HAL: 失败/超时
HAL-->>SC: onDatagramSendResult(RETRYING)
SC->>SC: 状态→DATAGRAM_RETRYING
SC->>HAL: 自动重试sendDatagram
else 发送失败
Modem-->>HAL: 错误
HAL-->>SC: onDatagramSendResult(ERROR)
SC-->>PIM: callback.accept(SATELLITE_RESULT_NETWORK_TIMEOUT等)
PIM-->>SM: IIntegerConsumer.accept(错误码)
SM-->>App: resultListener.accept(错误码)
end
三、短信接收流程
分步骤
| 步骤 | 层级 | 动作 | 关键类/方法 |
|---|
| 1 | Modem层 | 卫星Modem收到下行数据帧,解析出datagram | Modem firmware |
| 2 | HAL层 | Modem通过unsolicited event上报到SatelliteService HAL | ISatelliteService.onSatelliteDatagramReceived() |
| 3 | 控制层 | SatelliteController 收到datagram回调,通过 ISatelliteDatagramCallback.onSatelliteDatagramReceived(datagramId, datagram, pendingCount, ack) 上报 | SatelliteController |
| 4 | Telephony层 | PhoneInterfaceManager 将回调转发给注册的 ISatelliteDatagramCallback | PhoneInterfaceManager.java:12969 |
| 5 | API层 | SatelliteManager 内部回调触发 SatelliteDatagramCallback.onSatelliteDatagramReceived(datagramId, datagram, pendingCount, ack) | SatelliteDatagramCallback.java |
| 6 | 应用层 | 短信App解码 SatelliteDatagram 中的byte[]为短信内容并显示 | 短信App |
| 7 | ACK | App调用 ackCallback.accept(null) 确认接收,若5分钟内未确认,Telephony会重发 | SatelliteDatagramCallback.java:42 |
主动拉取模式(存储转发)
当终端重新捕获卫星信号时,App需主动拉取待接收消息:
时序图(Mermaid)
sequenceDiagram
participant Modem as Modem
participant HAL as SatelliteService(HAL)
participant SC as SatelliteController
participant PIM as PhoneInterfaceManager
participant SM as SatelliteManager
participant App as 短信App
Note over Modem,App: 即时下发模式
Modem->>HAL: 卫星数据帧→datagram
HAL->>SC: onSatelliteDatagramReceived(datagramId, datagram, pendingCount)
SC->>PIM: ISatelliteDatagramCallback.onSatelliteDatagramReceived()
PIM->>SM: 回调转发
SM->>App: SatelliteDatagramCallback.onSatelliteDatagramReceived(id, datagram, pendingCount, ack)
App->>App: 解码datagram显示短信
App->>SM: ack.accept(null) [5分钟内必须确认]
SM->>PIM: IVoidConsumer.accept()
PIM->>SC: 确认接收
SC->>HAL: 确认接收
Note over Modem,App: 主动拉取模式(存储转发)
App->>SM: pollPendingDatagrams(executor, listener)
SM->>PIM: ITelephony.pollPendingDatagrams(callback)
PIM->>SC: pollPendingDatagrams(callback)
SC->>HAL: 请求检查pending datagrams
HAL->>Modem: 查询
Modem-->>HAL: 返回pending datagrams
HAL->>SC: onSatelliteDatagramReceived()
SC->>PIM: 回调
PIM->>SM: 回调
SM->>App: onSatelliteDatagramReceived()
四、卫星短信特有机制
1. 长延迟与重试
| 机制 | 说明 |
|---|
SATELLITE_MODEM_STATE_DATAGRAM_RETRYING | Modem状态=3,表示datagram正在重试发送 |
SATELLITE_RESULT_NETWORK_TIMEOUT (17) | 网络超时错误码,卫星链路特有的超时 |
SATELLITE_RESULT_MODEM_TIMEOUT (24) | Modem超时错误码 |
SATELLITE_RESULT_NOT_REACHABLE (18) | 卫星不可达错误码 |
| 5分钟ACK超时 | 接收方若5分钟内未调用 ack.accept(),Telephony会重发datagram |
2. 受限消息长度
| 机制 | 说明 |
|---|
SatelliteCapabilities.getMaxBytesPerOutgoingDatagram() | Modem上报的每条datagram最大字节数 |
DATAGRAM_TYPE_SMS (6) | 专门标识短信类型的datagram |
| 客户端分段 | 超长短信由App自行分段为多个datagram发送(非框架层分片) |
3. 紧急短信优先级
| Datagram类型 | 值 | 说明 |
|---|
DATAGRAM_TYPE_SOS_MESSAGE | 1 | SOS紧急消息,最高优先级 |
DATAGRAM_TYPE_LAST_SOS_MESSAGE_STILL_NEED_HELP | 4 | 最后一条SOS,仍需帮助 |
DATAGRAM_TYPE_LAST_SOS_MESSAGE_NO_HELP_NEEDED | 5 | 最后一条SOS,不再需要帮助 |
DATAGRAM_TYPE_SMS | 6 | 普通短信 |
DATAGRAM_TYPE_KEEP_ALIVE | 3 | 保活/检查入站消息 |
4. 卫星波束切换
| 机制 | 说明 |
|---|
SatelliteAccessController | 监控区域变化(国家代码变更、位置设置变更),触发重新评估卫星通信允许状态 |
EVENT_COUNTRY_CODE_CHANGED | 国家代码变更事件,可能触发卫星区域切换 |
updateSystemSelectionChannels() | 向Modem更新系统选择通道(波束/频点信息) |
SatelliteRegionalConfig | 每个区域配置包含earfcn列表,切换区域时更新 |
5. 卫星Modem状态机
| 状态 | 值 | 说明 |
|---|
SATELLITE_MODEM_STATE_IDLE | 0 | 空闲 |
SATELLITE_MODEM_STATE_LISTENING | 1 | 正在监听卫星信号 |
SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING | 2 | 正在传输datagram |
SATELLITE_MODEM_STATE_DATAGRAM_RETRYING | 3 | datagram传输重试中 |
SATELLITE_MODEM_STATE_OFF | 4 | 卫星关闭 |
SATELLITE_MODEM_STATE_UNAVAILABLE | 5 | 卫星不可用 |
SATELLITE_MODEM_STATE_NOT_CONNECTED | 6 | 未连接卫星 |
SATELLITE_MODEM_STATE_CONNECTED | 7 | 已连接卫星 |
SATELLITE_MODEM_STATE_ENABLING_SATELLITE | 8 | 正在启用卫星 |
SATELLITE_MODEM_STATE_DISABLING_SATELLITE | 9 | 正在禁用卫星 |
五、与地面 SMS 的对比
| 对比维度 | 地面 SMS | 卫星 SMS (Android 16) |
|---|
| API入口 | SmsManager.sendTextMessage() | SatelliteManager.sendDatagram(DATAGRAM_TYPE_SMS) |
| 协议栈 | 3GPP TS 23.040/24.011, SMS over NAS/PP | 卫星私有协议,datagram封装(byte[]) |
| 分发器 | GsmSmsDispatcher / CdmaSmsDispatcher | SatelliteController → ISatelliteService |
| RIL命令 | RIL_REQUEST_SEND_SMS | ISatelliteService.sendDatagram() (HAL) |
| 消息格式 | 3GPP TPDU (160字符/段) | SatelliteDatagram (byte[], 长度由 maxBytesPerOutgoingDatagram 限制) |
| 典型时延 | 1~5秒 | 数秒~数分钟 |
| 接收方式 | RIL_UNSOL_RESPONSE_NEW_SMS → SMS_RECEIVED_ACTION 广播 | SatelliteDatagramCallback.onSatelliteDatagramReceived() 回调 + pollPendingDatagrams() 主动拉取 |
| 送达报告 | deliveryIntent (TP-SC-STATUS-REPORT) | SATELLITE_RESULT_SUCCESS 回调,无标准送达报告 |
| 重试机制 | SmsDispatcher 内部重试 | SATELLITE_MODEM_STATE_DATAGRAM_RETRYING,Modem自动重试 |
| 长短信 | 框架层自动分片(concat ref) | App自行分段为多个datagram |
| 存储转发 | SMSC存储转发,终端开机后下发 | pollPendingDatagrams() + DATAGRAM_TYPE_CHECK_PENDING_INCOMING_SMS |
| ACK机制 | CP-ACK + RP-ACK (层2/层3) | Consumer<Void> ack 回调(5分钟超时) |
| 用户感知 | 即时发送/接收 | 需对准卫星、高延迟、可能需等待卫星过境 |
| 权限 | SEND_SMS / RECEIVE_SMS | SATELLITE_COMMUNICATION (SystemApi) |
六、Android 关键代码与配置位置
| 类/文件 | 路径 | 说明 |
|---|
SatelliteManager | frameworks/base/telephony/java/android/telephony/satellite/SatelliteManager.java | 卫星通信公共API,含 sendDatagram()、pollPendingDatagrams()、registerForIncomingDatagram() |
SatelliteDatagram | frameworks/base/telephony/java/android/telephony/satellite/SatelliteDatagram.java | datagram数据结构(byte[]封装) |
SatelliteDatagramCallback | frameworks/base/telephony/java/android/telephony/satellite/SatelliteDatagramCallback.java | 接收datagram回调接口 |
SatelliteCapabilities | frameworks/base/telephony/java/android/telephony/satellite/SatelliteCapabilities.java | 卫星能力(含 maxBytesPerOutgoingDatagram) |
SatelliteAccessController | packages/services/Telephony/src/com/android/phone/satellite/accesscontrol/SatelliteAccessController.java | 区域访问控制 |
PhoneInterfaceManager | packages/services/Telephony/src/com/android/phone/PhoneInterfaceManager.java | ITelephony实现,桥接 SatelliteManager 与 SatelliteController |
SatelliteController | com.android.internal.telephony.satellite.SatelliteController | 卫星核心控制器(本代码库中未包含源码) |
ISatelliteService | HIDL/AIDL HAL接口 | 卫星HAL服务接口,与Modem交互 |
七、调试与测试建议
logcat 标签
| Tag | 说明 |
|---|
SatelliteManager | API层日志 |
SatelliteController | 控制层日志 |
SatelliteAccessController | 区域访问控制日志 |
SatelliteService | HAL层日志 |
PhoneInterfaceManager | ITelephony桥接层日志 |
关键调试命令
adb shell dumpsys phone | grep -A 50 "SatelliteController"
adb shell dumpsys phone | grep -A 30 "SatelliteAccessController"
adb shell dumpsys phone | grep -i "SatelliteCapabilities"
CTS 测试
| 测试类 | 说明 |
|---|
CtsSatelliteTest | 卫星通信CTS测试 |
setIsSatelliteCommunicationAllowedForCurrentLocationCache() | CTS设置允许状态缓存 |
allow_mock_modem | persist.radio.allow_mock_modem 属性控制是否允许mock modem测试 |
toolName: todo_write
status: success
Todos updated: 5 items
关键发现总结:Android 16 的卫星短信架构与传统 SMS 完全解耦,不经过 SmsDispatcher,而是通过 SatelliteManager.sendDatagram(DATAGRAM_TYPE_SMS) 走独立的 Datagram 通道。SatelliteController(源码不在本代码库中)是核心枢纽,连接 PhoneInterfaceManager 与卫星 HAL 服务。接收侧采用回调 + 主动拉取双模式,并有5分钟ACK超时保障可靠性。