卫星通信短信收发流程分析

0 阅读6分钟

一、概述:卫星短信的特点与挑战

核心发现

基于 Android 16 代码分析,卫星短信不走传统 SmsDispatcher 路径,而是通过 SatelliteManager.sendDatagram()Datagram(数据报) 方式收发。这意味着卫星短信与地面 SMS 是 完全独立的通道

卫星短信的挑战

挑战说明
高延迟RTT 500ms~数秒,远超地面 SMS
间歇性覆盖卫星非持续可见,需等待窗口
受限消息长度卫星数据报容量有限
非实时送达需存储转发机制
低功耗要求终端需控制唤醒频率

二、短信发送流程

时序图

App (Gateway/短信应用)
  │
  │ 1. SatelliteManager.sendDatagram(DATAGRAM_TYPE_SMS, datagram, ...)
  ↓
SatelliteManager
  │
  │ 2. ITelephony.sendDatagram(datagramType, datagram, needFullScreenPointingUI, callback)
  ↓
Telephony Service (ITelephony AIDL)
  │
  │ 3. 调用 ISatellite.sendSatelliteDatagram(datagram, isEmergency, resultCallback)
  ↓
SatelliteImplBase (Vendor Service)
  │
  │ 4. 厂商实现:调用 Vendor HAL / Modem
  ↓
Satellite Modem
  │
  │ 5. 卫星链路发送(NAS PDU / 专用通道)
  ↓
卫星
  │
  │ 6. 返回发送结果
  ↓
ISatelliteListener → Framework → App

详细步骤

步骤 1:应用层发起

卫星短信 不使用 SmsManager.sendTextMessage(),而是通过 SatelliteManager.sendDatagram()

// SatelliteManager.java:2289
public void sendDatagram(@DatagramType int datagramType,
        @NonNull SatelliteDatagram datagram, boolean needFullScreenPointingUI,
        @NonNull @CallbackExecutor Executor executor,
        @SatelliteResult @NonNull Consumer<Integer> resultListener)

关键参数:

  • datagramType = DATAGRAM_TYPE_SMS (值=6):标识这是 SMS 类型数据报
  • datagram:已编码的 SatelliteDatagram(byte[] 格式,由 Gateway 应用加密/编码)
  • needFullScreenPointingUI:是否需要全屏指向 UI

步骤 2:通过 ITelephony 传递到 Telephony Service

// SatelliteManager.java:2307
telephony.sendDatagram(datagramType, datagram,
        needFullScreenPointingUI, internalCallback);

步骤 3:Telephony Service 调用 ISatellite AIDL

Telephony 内部将请求转发到 Vendor Service 的 ISatellite.sendSatelliteDatagram()

// ISatellite.aidl
void sendSatelliteDatagram(in SatelliteDatagram datagram, in boolean isEmergency,
        in IIntegerConsumer resultCallback);

步骤 4:Vendor Service 实现

OEM 厂商在 SatelliteImplBase.sendSatelliteDatagram() 中实现真正的发送逻辑:

  • 调用 Vendor HAL
  • Modem 执行卫星随机接入
  • 将 SMS 数据封装到卫星信令通道

步骤 5:卫星链路发送

  • 3GPP NTN:SMS 封装在 NAS PDU 中,走控制平面,无需建立数据承载
  • 私有卫星系统(如北斗):通过 RDSS 通道发送短报文

步骤 6:状态回调

发送结果通过 IIntegerConsumer resultCallback 返回,可能的错误码包括:

错误码含义
SATELLITE_RESULT_SUCCESS发送成功
SATELLITE_RESULT_NETWORK_TIMEOUT网络超时
SATELLITE_RESULT_NOT_REACHABLE卫星不可达
SATELLITE_RESULT_ACCESS_BARRED接入被拒
SATELLITE_RESULT_REQUEST_ABORTED请求被中止

三、短信接收流程

时序图

卫星
  │
  │ 1. 下发 SMS 数据报
  ↓
Satellite Modem
  │
  │ 2. ISatelliteListener.onSatelliteDatagramReceived(datagram, pendingCount)
  ↓
SatelliteImplBase (Vendor Service)
  │
  │ 3. 回调到 Telephony Framework
  ↓
Telephony Service
  │
  │ 4. ISatelliteDatagramCallback.onSatelliteDatagramReceived(datagramId, datagram, pendingCount, ack)
  ↓
SatelliteManager → SatelliteDatagramCallback
  │
  │ 5. App 收到数据报,5分钟内必须 ack
  ↓
App (Gateway/短信应用)

详细步骤

步骤 1-2:Modem 接收并上报

Modem 收到卫星数据报后,Vendor Service 通过 ISatelliteListener 回调:

// ISatelliteListener.aidl
void onSatelliteDatagramReceived(in SatelliteDatagram datagram, in int pendingCount);

步骤 3-4:Framework 分发到应用

应用需先注册接收回调:

// SatelliteManager.java:2134
@SatelliteResult public int registerForIncomingDatagram(
        @NonNull Executor executor,
        @NonNull SatelliteDatagramCallback callback)

当有数据报到达时,回调触发:

// SatelliteDatagramCallback.java
void onSatelliteDatagramReceived(long datagramId, SatelliteDatagram datagram,
        int pendingCount, Consumer<Void> callback);

关键机制:5 分钟 ACK 超时

// SatelliteDatagramCallback.java 注释
// If the callback is not received within five minutes,
// Telephony will resend the datagram.

如果应用在 5 分钟内未调用 callback.accept(null) 确认,Telephony 会重新发送该数据报。

步骤 5:主动拉取(Poll)

对于存储转发的场景,应用可以主动拉取待接收的数据报:

// SatelliteManager.java:2232
public void pollPendingDatagrams(Executor executor, Consumer<Integer> resultListener)

对应的 Vendor 接口:

// ISatellite.aidl
void pollPendingSatelliteDatagrams(in IIntegerConsumer resultCallback);

四、卫星短信特有机制

1. Datagram 类型体系

卫星短信不是传统 SMS,而是通过 Datagram 承载:

类型用途
DATAGRAM_TYPE_SOS_MESSAGE1SOS 紧急消息
DATAGRAM_TYPE_LOCATION_SHARING2位置共享
DATAGRAM_TYPE_KEEP_ALIVE3保活/检查入消息
DATAGRAM_TYPE_SMS6SMS 短信
DATAGRAM_TYPE_CHECK_PENDING_INCOMING_SMS7检查待接收 SMS

2. 数据报传输状态机

IDLE → SENDING → SEND_SUCCESS / SEND_FAILED → IDLE
IDLE → RECEIVING → RECEIVE_SUCCESS / RECEIVE_NONE / RECEIVE_FAILED → IDLE
IDLE → WAITING_TO_CONNECT → (连接卫星后继续) → IDLE

通过 SatelliteTransmissionUpdateCallback 监听状态变化:

void onSendDatagramStateChanged(int state, int sendPendingCount, int errorCode);
void onReceiveDatagramStateChanged(int state, int receivePendingCount, int errorCode);

3. 紧急短信优先级

  • DATAGRAM_TYPE_SOS_MESSAGE (1) 优先级最高
  • sendSatelliteDatagramisEmergency 参数标识紧急消息
  • Modem 侧可能为紧急消息分配更高的卫星接入优先级

4. 存储转发与主动拉取

卫星链路非实时,接收流程有两种模式:

模式触发方式接口
被动接收Modem 收到数据后回调ISatelliteListener.onSatelliteDatagramReceived
主动拉取应用主动查询pollPendingDatagrams() / DATAGRAM_TYPE_CHECK_PENDING_INCOMING_SMS

5. 卫星监听模式

// ISatellite.aidl
void requestSatelliteListeningEnabled(in boolean enable, in int timeout,
        in IIntegerConsumer resultCallback);
  • timeout:Modem 等待下一个入站页面的时间
  • 超时后自动禁用监听模式,节省功耗

6. 地面网络扫描

// ISatellite.aidl
void enableTerrestrialNetworkScanWhileSatelliteModeIsOn(in boolean enabled,
        in IIntegerConsumer errorCallback);

卫星模式下允许扫描地面网络,当用户不活跃时检查是否有地面网络可用。


五、与地面 SMS 的对比

维度地面 SMS卫星 SMS (Android 16)
API 入口SmsManager.sendTextMessage()SatelliteManager.sendDatagram()
协议栈3GPP TS 23.040/24.0113GPP NTN NAS PDU / 私有协议
传输通道SmsDispatcherRILJ → ModemITelephonyISatellite → Vendor Service → Modem
消息格式GSM/3GPP SMS PDUSatelliteDatagram (byte[])
消息长度160 字符/条由卫星提供商决定(更受限)
典型时延1-5 秒5 秒~数分钟
送达报告deliveryIntent 实时IIntegerConsumer 回调(延迟大)
接收模式Modem 主动上报 +CMT被动回调 + 主动 pollPendingDatagrams
ACK 机制acknowledgeLastIncomingSms() 即时5 分钟内 Consumer<Void> 确认
分片支持sendMultipartTextMessage应用层自行处理
存储转发SMSC 存储卫星网络侧 + 终端 poll
紧急优先无特殊优先级isEmergency=true + DATAGRAM_TYPE_SOS_MESSAGE

六、Android 关键代码与配置位置

Framework 层

文件作用
SatelliteManager.java应用 API,sendDatagram() / pollPendingDatagrams() / registerForIncomingDatagram()
SatelliteDatagram.java数据报模型,byte[] mData
SatelliteDatagramCallback.java接收回调,onSatelliteDatagramReceived()
SatelliteTransmissionUpdateCallback.java传输状态回调

Vendor Service 层(stub)

文件作用
ISatellite.aidlFramework → Vendor 接口,sendSatelliteDatagram() / pollPendingSatelliteDatagrams()
ISatelliteListener.aidlVendor → Framework 回调,onSatelliteDatagramReceived()
SatelliteImplBase.java厂商需继承的基类
SatelliteService.javaService 入口
SatelliteGatewayService.javaGateway 服务(绑定/解绑生命周期管理)

关键配置

配置说明
config_satellite_service_packageVendor SatelliteService 的包名
config_satellite_gateway_service_packageGateway 服务包名
android.permission.BIND_SATELLITE_SERVICE绑定卫星服务权限
android.permission.SATELLITE_COMMUNICATION应用调用卫星 API 权限

七、调试与测试建议

logcat 标签

Tag用途
SatelliteManager应用 API 调用日志
SatelliteServiceService 绑定日志
SatelliteImplBaseVendor Service 方法调用日志

关键调试点

  1. 发送流程:在 SatelliteManager.sendDatagram() 打断点,跟踪 ITelephony.sendDatagram() 调用
  2. 接收流程:在 SatelliteDatagramCallback.onSatelliteDatagramReceived() 打断点
  3. 状态变化:监听 SatelliteTransmissionUpdateCallback.onSendDatagramStateChanged()
  4. ACK 超时:注意 5 分钟 ACK 超时机制,未确认会重发

模拟测试

  • 使用 DATAGRAM_TYPE_SOS_MESSAGE 模拟紧急短信
  • 使用 pollPendingDatagrams() 模拟存储转发场景
  • 通过 requestSatelliteListeningEnabled(true, timeout) 控制监听窗口