Modem 上报卫星信号变化通知的完整流程分析

6 阅读14分钟

一、总体流程概览

Android 16 中卫星信号变化通知存在 两条并行路径,分别服务于不同的卫星通信模式:

路径模式触发源通知链路
路径A:OEM卫星模式独立卫星(如SOS紧急通信)ISatellite HAL → SatelliteServiceISatelliteListener.onNtnSignalStrengthChanged()
路径B:运营商NTN漫游模式Carrier Roaming NB-IoT NTNIRadio AIDL → RILJ → PhoneSignalStrengthController → TelephonyRegistryManager
总体信号流(路径A - OEM卫星模式):

Modem固件 ──[QMI/AT/共享内存]──► Vendor RIL (rild)
    │                                    │
    │  卫星信号测量值变化                    │  解析为 stub.NtnSignalStrength
    │                                    ▼
    │                           SatelliteService (厂商实现)
    │                                    │
    │                              [Binder IPC]
    │                                    │
    │                                    ▼
    │                    ISatelliteListener.onNtnSignalStrengthChanged()
    │                                    │
    │                                    ▼
    │                    SatelliteModemInterface.VendorListener
    │                                    │
    │                          [Registrant.notifyResult]
    │                                    │
    │                                    ▼
    │                    SatelliteController.EVENT_NTN_SIGNAL_STRENGTH_CHANGED
    │                                    │
    │                     ┌──────────────┴──────────────┐
    │                     ▼                              ▼
    │     handleEventNtnSignalStrengthChanged()    updateLastNotifiedCarrierRoaming
    │         (缓存+回调INtnSignalStrength         NtnSignalStrengthAndNotify()
    │          StrengthCallback注册者)                   │
    │                                                    ▼
    │                                        Phone.notifyCarrierRoamingNtnSignalStrengthChanged()
    │                                                    │
    │                                                    ▼
    │                                        DefaultPhoneNotifierTelephonyRegistryManager
    │                                                    │
    │                                              [Binder IPC]
    │                                                    │
    │                                                    ▼
    │                                           TelephonyRegistry (系统服务进程)
    │                                                    │
    │                                              [Binder回调]
    │                                                    │
    │                                                    ▼
    │                                        ITelephonyListener.onCarrierRoamingNtnSignalStrengthChanged()
    │                                                    │
    │                                     ┌─────────────┼─────────────┐
    │                                     ▼             ▼             ▼
    │                               SystemUI       卫星应用       ConnectivityService

总体信号流(路径B - 运营商NTN漫游模式):

Modem固件 ──[IRadio AIDL]──► RILJ (RIL.java)
    │                              │
    │  3GPP R17 NTN信号测量         │  RIL_UNSOL_SIGNAL_STRENGTH
    │                              ▼
    │                    SignalStrengthController
    │                              │
    │                    [Registrant通知]
    │                              │
    │              ┌───────────────┼───────────────┐
    │              ▼                               ▼
    │    SatelliteController               Phone.notifySignalStrength()
    │    EVENT_SIGNAL_STRENGTH_CHANGED             │
    │              │                               ▼
    │              ▼                    TelephonyRegistryManagerupdateLastNotifiedCarrierRoaming          │
    │    NtnSignalStrengthAndNotify()        [Binder IPC]
    │                                          │
    │                                          ▼
    │                                  TelephonyRegistry → 应用层

二、各层级详细说明

2.1 Modem → RIL 驱动

2.1.1 Modem 侧信号检测机制

Modem 固件对卫星信号的检测采用 周期测量 + 事件触发 + 门限比较 的混合策略:

检测方式说明典型场景
周期测量Modem 以固定间隔(通常 1~5 秒)测量 RSSI/SNR卫星连接建立后的持续监测
事件触发信号跨越预设门限时立即上报信号从"有"变为"无"或反向
门限比较仅当信号等级(Level)变化时才上报减少不必要的上报,节省功耗

关键点:Modem 并非每次测量都上报,而是仅当 signalStrengthLevel 发生变化时才触发上报。这是一种 事件驱动的上报模型,而非周期轮询模型。

2.1.2 Modem → AP 的上报通道

Android 16 中卫星信号上报存在两种通道,对应两种卫星模式:

通道1:ISatellite HAL 接口(OEM卫星模式)

Modem固件 → Vendor RIL → SatelliteService (厂商APK)
    → ISatelliteListener.onNtnSignalStrengthChanged(stub.NtnSignalStrength)

这是 Android 16 中 专用的卫星信号上报通道。Modem 通过厂商私有协议(QMI/AT/共享内存)将卫星信号数据传递给 Vendor RIL,Vendor RIL 内的 SatelliteService 实现将原始数据转换为 android.telephony.satellite.stub.NtnSignalStrength 格式,再通过 ISatelliteListener AIDL 回调接口上报给 Framework。

通道2:IRadio AIDL 接口(运营商NTN漫游模式)

Modem固件 → IRadio AIDL → RILJ (RIL.java)
    → RIL_UNSOL_SIGNAL_STRENGTH → SignalStrengthController

当终端通过运营商 NB-IoT NTN 网络接入时(如 T-Mobile NTN 漫游),卫星信号变化通过标准的 3GPP 信号强度上报机制传递,即 IRadio 1.6+currentSignalStrength() indication。

2.1.3 典型上报原语

OEM卫星模式(通过 ISatellite HAL):

// AIDL 回调原型
oneway void onNtnSignalStrengthChanged(in NtnSignalStrength ntnSignalStrength);

// NtnSignalStrength 数据结构
parcelable NtnSignalStrength {
    int signalStrengthLevel;  // 0=NONE, 1=LOW, 2=MEDIUM, 3=HIGH, 4=GOOD
}

运营商NTN漫游模式(通过 IRadio AIDL):

// IRadio indication
oneway void currentSignalStrength(int type, in SignalStrength signalStrength);

// SignalStrength 中包含 NTN 相关字段
// 3GPP R17 扩展了 SignalStrength 以支持非地面网络测量值

2.2 RIL 驱动 → RILJ

2.2.1 SatelliteService(厂商实现层)

SatelliteService 是厂商实现的系统服务,运行在独立进程中。它负责:

  1. 解析 Modem 原始数据:将厂商私有协议(QMI/AT等)的卫星信号数据解析为 Android 定义的 stub.NtnSignalStrength
  2. 通过 ISatellite.aidl 上报:调用 ISatelliteListener.onNtnSignalStrengthChanged() 将信号变化通知 Framework

关键代码路径(SatelliteModemInterface.java:172-177):

// SatelliteModemInterface 内部的 VendorListener
public void onNtnSignalStrengthChanged(
        android.telephony.satellite.stub.NtnSignalStrength ntnSignalStrength) {
    if (notifyResultIfExpectedListener()) {
        mNtnSignalStrengthChangedRegistrants.notifyResult(
                SatelliteServiceUtils.fromNtnSignalStrength(ntnSignalStrength));
    }
}

2.2.2 信号强度上报的启停控制

Framework 并非始终接收卫星信号上报,而是通过 DeviceStateMonitor 根据设备状态动态控制:

控制链路

DeviceStateMonitor.shouldEnableSignalStrengthReports()
    → mSignalStrengthReportDecisionCallbackRegistrants.notifyResult(true/false)
    → SatelliteController.CMD_UPDATE_NTN_SIGNAL_STRENGTH_REPORTINGhandleCmdUpdateNtnSignalStrengthReporting(shouldReport)
    → SatelliteModemInterface.startSendingNtnSignalStrength() / stopSendingNtnSignalStrength()
    → ISatellite.startSendingNtnSignalStrength() / stopSendingNtnSignalStrength()
    → SatelliteService → Modem

关键源码(DeviceStateMonitor.java:393-402):

private boolean shouldEnableSignalStrengthReports() {
    return shouldEnableHighPowerConsumptionIndications()
            || (mIsAlwaysSignalStrengthReportingEnabled && mIsRadioOn);
}

启用条件(满足任一即可):

  • 高功耗场景:屏幕点亮、充电中、或正在进行数据传输
  • 常驻监听模式:系统服务注册了 isAlwaysSignalStrengthReportingEnabled 且 Radio 已开启

这意味着:屏幕熄灭且无数据传输时,Modem 将停止上报卫星信号变化,以节省功耗。

2.2.3 类型转换

SatelliteServiceUtils.java:252-255

public static NtnSignalStrength fromNtnSignalStrength(
        android.telephony.satellite.stub.NtnSignalStrength ntnSignalStrength) {
    return new NtnSignalStrength(ntnSignalStrength.signalStrengthLevel);
}

将 HAL 层的 stub.NtnSignalStrength(仅含 signalStrengthLevel 整数字段)转换为 Framework 层的 android.telephony.satellite.NtnSignalStrength 对象。


2.3 RILJ → Telephony 框架

2.3.1 SatelliteController 接收信号变化

SatelliteController 在初始化时注册监听(SatelliteController.java:4850):

mSatelliteModemInterface.registerForNtnSignalStrengthChanged(
        this, EVENT_NTN_SIGNAL_STRENGTH_CHANGED, null);

当收到信号变化通知时,Handler 处理逻辑(SatelliteController.java:1987-1995):

case EVENT_NTN_SIGNAL_STRENGTH_CHANGED: {
    ar = (AsyncResult) msg.obj;
    if (ar.result == null) {
        ploge("EVENT_NTN_SIGNAL_STRENGTH_CHANGED: result is null");
    } else {
        handleEventNtnSignalStrengthChanged((NtnSignalStrength) ar.result);
        updateLastNotifiedCarrierRoamingNtnSignalStrengthAndNotify(getSatellitePhone());
    }
    break;
}

2.3.2 信号变化的两个处理分支

分支1:回调注册者通知SatelliteController.java:5049-5068

private void handleEventNtnSignalStrengthChanged(NtnSignalStrength ntnSignalStrength) {
    synchronized (mNtnSignalsStrengthLock) {
        mNtnSignalStrength = ntnSignalStrength;  // 缓存最新值
    }
    mSessionMetricsStats.updateMaxNtnSignalStrengthLevel(ntnSignalStrength.getLevel());

    // 通知所有通过 SatelliteManager 注册的 INtnSignalStrengthCallback
    mNtnSignalStrengthChangedListeners.values().forEach(listener -> {
        try {
            listener.onNtnSignalStrengthChanged(ntnSignalStrength);
        } catch (RemoteException e) {
            deadCallersList.add(listener);
        }
    });
}

分支2:运营商NTN漫游信号通知SatelliteController.java:9024-9042

protected void updateLastNotifiedCarrierRoamingNtnSignalStrengthAndNotify(Phone phone) {
    if (!mFeatureFlags.carrierRoamingNbIotNtn()) return;
    
    NtnSignalStrength currSignalStrength = getCarrierRoamingNtnSignalStrength(phone);
    int subId = phone.getSubId();
    synchronized (mSatelliteConnectedLock) {
        NtnSignalStrength lastNotifiedSignalStrength =
                mLastNotifiedCarrierRoamingNtnSignalStrength.get(subId);
        // 仅当信号等级变化时才通知(防抖机制)
        if (lastNotifiedSignalStrength == null
                || lastNotifiedSignalStrength.getLevel() != currSignalStrength.getLevel()) {
            mLastNotifiedCarrierRoamingNtnSignalStrength.put(subId, currSignalStrength);
            phone.notifyCarrierRoamingNtnSignalStrengthChanged(currSignalStrength);
        }
    }
}

关键设计getCarrierRoamingNtnSignalStrength() 根据当前卫星模式决定信号来源(SatelliteController.java:8980-9003):

private NtnSignalStrength getCarrierRoamingNtnSignalStrength(Phone phone) {
    NtnSignalStrength carrierRoamingNtnSignalStrength = new NtnSignalStrength(NTN_SIGNAL_STRENGTH_NONE);

    if (isInCarrierRoamingNbIotNtn(phone)) {
        // NB-IoT NTN 模式:使用 ISatellite HAL 上报的信号值
        if (isInConnectedState()) {
            synchronized (mNtnSignalsStrengthLock) {
                carrierRoamingNtnSignalStrength = mNtnSignalStrength;
            }
        }
    } else if (isInSatelliteModeForCarrierRoaming(phone)) {
        // 运营商漫游模式:使用 Phone 的 SignalStrength
        ServiceState serviceState = phone.getServiceState();
        if (serviceState.getState() != ServiceState.STATE_OUT_OF_SERVICE) {
            carrierRoamingNtnSignalStrength = new NtnSignalStrength(
                    phone.getSignalStrength().getLevel());
        }
    }
    return carrierRoamingNtnSignalStrength;
}

2.3.3 蜂窝信号变化触发卫星信号更新

除了 ISatellite HAL 主动上报外,蜂窝信号变化也会触发卫星信号更新SatelliteController.java:6289-6293):

private void registerForSignalStrengthChanged() {
    for (Phone phone : PhoneFactory.getPhones()) {
        phone.getSignalStrengthController().registerForSignalStrengthChanged(this,
                EVENT_SIGNAL_STRENGTH_CHANGED, phone.getPhoneId());
    }
}

当 Phone 的 SignalStrengthController 报告信号变化时(SatelliteController.java:2208-2214):

case EVENT_SIGNAL_STRENGTH_CHANGED: {
    ar = (AsyncResult) msg.obj;
    int phoneId = (int) ar.userObj;
    updateLastNotifiedCarrierRoamingNtnSignalStrengthAndNotify(
            PhoneFactory.getPhone(phoneId));
    break;
}

2.4 Telephony 框架 → 系统服务

2.4.1 Phone → TelephonyRegistryManager

信号变化通过 Phone 对象传递到 TelephonyRegistryManager(Phone.java:5448-5453):

public void notifyCarrierRoamingNtnSignalStrengthChanged(
        @NonNull NtnSignalStrength ntnSignalStrength) {
    mNotifier.notifyCarrierRoamingNtnSignalStrengthChanged(this, ntnSignalStrength);
}

DefaultPhoneNotifier 转发(DefaultPhoneNotifier.java:355-359):

public void notifyCarrierRoamingNtnSignalStrengthChanged(Phone sender,
        @NonNull NtnSignalStrength ntnSignalStrength) {
    mTelephonyRegistryMgr.notifyCarrierRoamingNtnSignalStrengthChanged(
            sender.getSubId(), ntnSignalStrength);
}

2.4.2 TelephonyRegistry 广播

TelephonyRegistry(运行在系统服务进程)收到通知后,遍历所有注册了 ITelephonyListener 的客户端,通过 Binder 回调 onCarrierRoamingNtnSignalStrengthChanged() 通知信号变化。

2.4.3 ConnectivityService 的处理

ConnectivityService 通过以下方式感知卫星信号变化:

  1. TelephonyRegistry 监听:注册 TelephonyCallback 监听信号强度变化
  2. NetworkAgent 评分调整:卫星网络通过 TelephonyNetworkAgent 上报网络质量,ConnectivityService 根据信号强度调整卫星网络的 NetworkScore
  3. 网络有效性判断:当卫星信号等级为 NTN_SIGNAL_STRENGTH_NONE 时,可能将卫星网络标记为无效

2.4.4 DeviceStateMonitor 的省电策略

DeviceStateMonitor 综合以下因素决定是否启用信号上报:

因素条件影响
屏幕状态亮屏启用上报
充电状态充电中启用上报
数据活动有数据传输启用上报
省电模式开启可能禁用上报
常驻监听系统服务注册始终启用

当设备进入低功耗状态(屏幕关闭、无数据传输),DeviceStateMonitor 会通知 SatelliteController 停止 Modem 的信号上报,从而节省电量。


2.5 系统服务 → 应用层

2.5.1 SystemUI 信号显示

SystemUI 通过两种方式获取卫星信号:

方式1:TelephonyManager 监听

// 注册 TelephonyCallback
telephonyManager.registerTelephonyCallback(executor, new TelephonyCallback() {
    @Override
    public void onCarrierRoamingNtnSignalStrengthChanged(NtnSignalStrength ntnSignalStrength) {
        // 更新状态栏卫星图标
        updateSatelliteSignalIcon(ntnSignalStrength.getLevel());
    }
});

方式2:SatelliteManager 监听

// 注册 NTN 信号强度回调
satelliteManager.registerForNtnSignalStrengthChanged(executor, callback);

信号等级到图标映射:

Level 值常量图标显示
0NTN_SIGNAL_STRENGTH_NONE无信号/卫星图标灰色
1NTN_SIGNAL_STRENGTH_LOW1格信号
2NTN_SIGNAL_STRENGTH_MEDIUM2格信号
3NTN_SIGNAL_STRENGTH_HIGH3格信号
4NTN_SIGNAL_STRENGTH_GOOD4格信号/满格

2.5.2 卫星消息/电话应用

卫星应用通过 SatelliteManager.registerForNtnSignalStrengthChanged() 注册回调,当信号变化时:

  • 信号为 NONE:提示用户"无法发送消息,请调整天线方向"
  • 信号为 LOW:提示"信号较弱,消息可能延迟"
  • 信号为 MEDIUM/HIGH/GOOD:允许发送消息

2.5.3 OEM 私有 API

OEM 应用可通过 SatelliteManager 的系统 API 访问卫星信号:

  • requestNtnSignalStrength(ResultReceiver):主动查询当前信号强度
  • registerForNtnSignalStrengthChanged(INtnSignalStrengthCallback):注册信号变化回调

三、关键数据结构与接口定义

3.1 NtnSignalStrength(Framework 层)

// android.telephony.satellite.NtnSignalStrength
public class NtnSignalStrength implements Parcelable {
    // 信号等级常量
    public static final int NTN_SIGNAL_STRENGTH_NONE = 0;
    public static final int NTN_SIGNAL_STRENGTH_LOW = 1;
    public static final int NTN_SIGNAL_STRENGTH_MEDIUM = 2;
    public static final int NTN_SIGNAL_STRENGTH_HIGH = 3;
    public static final int NTN_SIGNAL_STRENGTH_GOOD = 4;

    private final int mLevel;  // 信号等级

    public NtnSignalStrength(@NtnSignalStrengthLevel int level) {
        mLevel = level;
    }

    public int getLevel() { return mLevel; }
}

3.2 NtnSignalStrength(HAL/Stub 层)

// android.telephony.satellite.stub.NtnSignalStrength
parcelable NtnSignalStrength {
    int signalStrengthLevel;  // 与 Framework 层等级常量一致
}

3.3 ISatelliteListener AIDL 接口

// ISatelliteListener.aidl
oneway interface ISatelliteListener {
    void onSatelliteModemStateChanged(int state);
    void onSatellitePositionInfoChanged(in PointingInfo pointingInfo);
    void onNtnSignalStrengthChanged(in NtnSignalStrength ntnSignalStrength);
    void onSatelliteCapabilitiesChanged(in SatelliteCapabilities capabilities);
    void onPendingDatagrams(int count);
    void onDatagramTransferStateChanged(int state);
    void onSatelliteSupportedStateChanged(boolean supported);
    void onRegistrationFailure(int causeCode);
    void onTerrestrialNetworkAvailableChanged(boolean isAvailable);
}

3.4 INtnSignalStrengthCallback AIDL 接口

// android.telephony.satellite.INtnSignalStrengthCallback
oneway interface INtnSignalStrengthCallback {
    void onNtnSignalStrengthChanged(in NtnSignalStrength ntnSignalStrength);
}

3.5 ISatellite AIDL 接口(信号相关方法)

// ISatellite.aidl 中的信号相关方法
oneway void requestSignalStrength(IIntegerConsumer callback, INtnSignalStrengthConsumer consumer);
oneway void startSendingNtnSignalStrength(IIntegerConsumer callback);
oneway void stopSendingNtnSignalStrength(IIntegerConsumer callback);

四、典型时序图

4.1 OEM卫星模式信号变化时序

Modem          Vendor RIL      SatelliteService    SatelliteModemInterface    SatelliteController    Phone    TelephonyRegistry    App
  │                │                 │                      │                        │                │           │              │
  │ 信号等级变化    │                 │                      │                        │                │           │              │
  │───────────────►│                 │                      │                        │                │           │              │
  │                │ 解析为           │                      │                        │                │           │              │
  │                │ stub.NtnSignal  │                      │                        │                │           │              │
  │                │────────────────►│                      │                        │                │           │              │
  │                │                 │                      │                        │                │           │              │
  │                │                 │ onNtnSignalStrength  │                        │                │           │              │
  │                │                 │ Changed(stub.NtnSS) │                        │                │           │              │
  │                │                 │─────────────────────►│                        │                │           │              │
  │                │                 │                      │                        │                │           │              │
  │                │                 │              [Binder IPC 跨进程]               │                │           │              │
  │                │                 │                      │                        │                │           │              │
  │                │                 │                      │ fromNtnSignalStrength()│                │           │              │
  │                │                 │                      │ notifyResult()         │                │           │              │
  │                │                 │                      │───────────────────────►│                │           │              │
  │                │                 │                      │                        │                │           │              │
  │                │                 │                      │                        │ 缓存mNtnSignal │           │              │
  │                │                 │                      │                        │ Strength       │           │              │
  │                │                 │                      │                        │                │           │              │
  │                │                 │                      │                        │──────┐         │           │              │
  │                │                 │                      │                        │ 分支1:回调     │           │              │
  │                │                 │                      │                        │ INtnSignal     │           │              │
  │                │                 │                      │                        │ Strength       │           │              │
  │                │                 │                      │                        │ Callback       │           │              │
  │                │                 │                      │                        │◄──────┘         │           │              │
  │                │                 │                      │                        │                │           │              │
  │                │                 │                      │                        │──────┐         │           │              │
  │                │                 │                      │                        │ 分支2:判断等级 │           │              │
  │                │                 │                      │                        │ 是否变化       │           │              │
  │                │                 │                      │                        │◄──────┘         │           │              │
  │                │                 │                      │                        │                │           │              │
  │                │                 │                      │                        │ notifyCarrier  │           │              │
  │                │                 │                      │                        │ RoamingNtn     │           │              │
  │                │                 │                      │                        │ SignalStrength │           │              │
  │                │                 │                      │                        │ Changed()      │           │              │
  │                │                 │                      │                        │───────────────►│           │              │
  │                │                 │                      │                        │                │           │              │
  │                │                 │                      │                        │                │ Telephony │              │
  │                │                 │                      │                        │                │ Registry  │              │
  │                │                 │                      │                        │                │ Manager   │              │
  │                │                 │                      │                        │                │──────────►│              │
  │                │                 │                      │                        │                │           │              │
  │                │                 │                      │                        │                │           │ [Binder      │
  │                │                 │                      │                        │                │           │  回调]       │
  │                │                 │                      │                        │                │           │─────────────►│
  │                │                 │                      │                        │                │           │              │

4.2 信号上报启停控制时序

DeviceStateMonitor        SatelliteController         SatelliteModemInterface      ISatellite (HAL)
      │                         │                            │                          │
  屏幕亮起/充电/数据活动         │                            │                          │
      │                         │                            │                          │
      │ shouldEnableSignal      │                            │                          │
      │ StrengthReports()=true  │                            │                          │
      │                         │                            │                          │
      │ notifyResult(true)      │                            │                          │
      │────────────────────────►│                            │                          │
      │                         │                            │                          │
      │                         │ CMD_UPDATE_NTN_SIGNAL      │                          │
      │                         │ STRENGTH_REPORTING         │                          │
      │                         │──────┐                     │                          │
      │                         │      │ handleCmdUpdate     │                          │
      │                         │      │ NtnSignalStrength   │                          │
      │                         │      │ Reporting(true)     │                          │
      │                         │◄─────┘                     │                          │
      │                         │                            │                          │
      │                         │ startSendingNtnSignal      │                          │
      │                         │ Strength()                 │                          │
      │                         │───────────────────────────►│                          │
      │                         │                            │                          │
      │                         │                            │ ISatellite.startSending  │
      │                         │                            │ NtnSignalStrength()      │
      │                         │                            │─────────────────────────►│
      │                         │                            │                          │
      │                         │                            │         Modem开始上报信号  │
      │                         │                            │                          │

4.3 典型上报频率

场景上报频率触发条件
信号等级变化事件驱动(立即)signalStrengthLevel 跨越等级阈值
信号稳定不上报等级未变化
屏幕亮起首次立即上报startSendingNtnSignalStrength()
屏幕熄灭停止上报stopSendingNtnSignalStrength()

五、卫星特有处理逻辑

5.1 信号等级模型

Android 16 的卫星信号强度采用 5级离散等级模型,而非蜂窝网络的连续 RSSI/RSRP 值:

NTN_SIGNAL_STRENGTH_NONE  (0) → 无卫星信号 / 未连接
NTN_SIGNAL_STRENGTH_LOW   (1) → 信号弱,仅支持紧急/短消息
NTN_SIGNAL_STRENGTH_MEDIUM(2) → 信号中等,可发送短信
NTN_SIGNAL_STRENGTH_HIGH  (3) → 信号良好,可进行数据传输
NTN_SIGNAL_STRENGTH_GOOD  (4) → 信号优秀,全功能可用

设计原因:卫星信号传播距离远(500~36000km),RSSI/SNR 的绝对值对用户无意义,离散等级更直观。

5.2 不同卫星系统的差异

卫星系统信号特征上报通道定制点
天通一号 (GEO)固定仰角,信号稳定ISatellite HAL厂商自定义等级映射
北斗短报文间歇通信窗口ISatellite HAL信号仅在窗口期有效
Iridium (LEO)高动态,信号快速变化ISatellite HAL需要更快的上报频率
Starlink D2DNR NTN,3GPP标准IRadio AIDL通过标准SignalStrength
T-Mobile NTNNB-IoT NTNIRadio AIDL运营商漫游模式

通用模型:所有卫星系统最终都映射到 NtnSignalStrength.signalStrengthLevel 的 0-4 等级。厂商在 SatelliteService 实现中负责将特定卫星系统的原始测量值映射到标准等级。

5.3 Demo 模式信号模拟

DemoSimulator 在演示模式下模拟卫星信号变化(DemoSimulator.java:131-135):

// NotConnectedState 进入时
NtnSignalStrength ntnSignalStrength = new NtnSignalStrength();
ntnSignalStrength.signalStrengthLevel = 0;  // 无信号
mISatelliteListener.onNtnSignalStrengthChanged(ntnSignalStrength);

// ConnectedState 进入时
NtnSignalStrength ntnSignalStrength = new NtnSignalStrength();
ntnSignalStrength.signalStrengthLevel = 2;  // 中等信号
mISatelliteListener.onNtnSignalStrengthChanged(ntnSignalStrength);

关键过滤逻辑(SatelliteModemInterface.java:202-206):

private boolean notifyResultIfExpectedListener() {
    // Demo listener 仅在 demo 模式下通知
    // Vendor listener 仅在真实模式下通知
    return mIsDemoListener == mSatelliteController.isDemoModeEnabled();
}

六、异常处理与优化策略

6.1 防抖机制(Level 变化过滤)

SatelliteController 在向 TelephonyRegistry 广播前实现了 等级变化防抖

// updateLastNotifiedCarrierRoamingNtnSignalStrengthAndNotify()
if (lastNotifiedSignalStrength == null
        || lastNotifiedSignalStrength.getLevel() != currSignalStrength.getLevel()) {
    // 仅当等级变化时才通知
    mLastNotifiedCarrierRoamingNtnSignalStrength.put(subId, currSignalStrength);
    phone.notifyCarrierRoamingNtnSignalStrengthChanged(currSignalStrength);
}

这意味着:即使 Modem 频繁上报,只要 signalStrengthLevel 不变,上层应用不会收到重复通知

6.2 连接滞后定时器(Hysteresis Timer)

卫星连接断开时,不会立即通知"无信号",而是启动滞后定时器(SatelliteController.java:6349-6351):

sendMessageDelayed(obtainMessage(EVENT_NOTIFY_NTN_HYSTERESIS_TIMED_OUT,
                phone.getPhoneId()),
        getSatelliteConnectionHysteresisTimeMillis(subId));

滞后时间由 CarrierConfig 配置:

private long getSatelliteConnectionHysteresisTimeMillis(int subId) {
    PersistableBundle config = getPersistableBundle(subId);
    return (config.getInt(KEY_SATELLITE_CONNECTION_HYSTERESIS_SEC_INT) * 1000L);
}

作用:防止卫星信号短暂中断导致的频繁连接/断开切换,提升用户体验。

6.3 NTN 资格滞后定时器

卫星 NTN 资格变化也有滞后机制(SatelliteController.java:6470-6481):

private void evaluateCarrierRoamingNtnEligibilityChange() {
    boolean eligible = isCarrierRoamingNtnEligible(getSatellitePhone());
    if (eligible) {
        if (shouldStartNtnEligibilityHysteresisTimer(eligible)) {
            startNtnEligibilityHysteresisTimer();  // 延迟通知"有资格"
        }
    } else {
        stopNtnEligibilityHysteresisTimer();
        updateLastNotifiedNtnEligibilityAndNotify(false);  // 立即通知"无资格"
    }
}

不对称策略

  • 变为"有资格":延迟通知(避免短暂信号触发)
  • 变为"无资格":立即通知(快速释放资源)

6.4 Modem 上报异常值处理

空值处理

case EVENT_NTN_SIGNAL_STRENGTH_CHANGED: {
    ar = (AsyncResult) msg.obj;
    if (ar.result == null) {
        ploge("EVENT_NTN_SIGNAL_STRENGTH_CHANGED: result is null");
        // 不更新缓存,保持上一次有效值
    }
}

请求失败处理

case EVENT_REQUEST_NTN_SIGNAL_STRENGTH_DONE: {
    if (errorCode == SATELLITE_RESULT_SUCCESS) {
        NtnSignalStrength ntnSignalStrength = (NtnSignalStrength) ar.result;
        if (ntnSignalStrength != null) {
            mNtnSignalStrength = ntnSignalStrength;
        } else {
            // 返回null时重置为 NONE
            if (mNtnSignalStrength.getLevel() != NTN_SIGNAL_STRENGTH_NONE) {
                mNtnSignalStrength = new NtnSignalStrength(NTN_SIGNAL_STRENGTH_NONE);
            }
        }
    } else {
        // 请求失败时重置为 NONE
        if (mNtnSignalStrength.getLevel() != NTN_SIGNAL_STRENGTH_NONE) {
            mNtnSignalStrength = new NtnSignalStrength(NTN_SIGNAL_STRENGTH_NONE);
        }
    }
}

6.5 主动查询的缓存优化

requestNtnSignalStrength() 优先使用缓存值,避免不必要的 Modem 请求(SatelliteController.java:3340-3360):

public void requestNtnSignalStrength(@NonNull ResultReceiver result) {
    synchronized (mNtnSignalsStrengthLock) {
        if (mNtnSignalStrength.getLevel() != NTN_SIGNAL_STRENGTH_NONE) {
            // 缓存可用,直接返回
            Bundle bundle = new Bundle();
            bundle.putParcelable(KEY_NTN_SIGNAL_STRENGTH, mNtnSignalStrength);
            result.send(SATELLITE_RESULT_SUCCESS, bundle);
            return;
        }
    }
    // 缓存不可用才请求 Modem
    sendRequestAsync(CMD_REQUEST_NTN_SIGNAL_STRENGTH, result, phone);
}

6.6 Modem 状态不一致恢复

当 Modem 上报的状态与 Framework 预期不一致时,自动禁用卫星(SatelliteController.java:5024-5035):

if (isSatelliteEnabledOrBeingEnabled() || isSatelliteBeingDisabled()) {
    notifyModemStateChangedToSessionController(state);
} else {
    // Telephony framework and modem are out of sync.
    plogw("Satellite modem is in a bad state. Disabling satellite modem now ...");
    mSatelliteDisabledRequest = new RequestSatelliteEnabledArgument(...);
    sendRequestAsync(CMD_SET_SATELLITE_ENABLED, mSatelliteDisabledRequest, null);
}

七、与其他模块的交互边界

7.1 交互矩阵

模块交互方式信号相关行为
ConnectivityServiceTelephonyNetworkAgent根据信号等级调整网络评分
SystemUITelephonyCallback显示卫星信号图标
SatelliteManagerINtnSignalStrengthCallback应用层信号变化回调
DeviceStateMonitorRegistrantList控制信号上报启停
SignalStrengthControllerRegistrant蜂窝信号变化触发卫星信号更新
SatelliteSessionController状态机转换信号变化影响会话状态
WifiService无直接交互不关心卫星信号
LocationManagerGNSS HAL卫星定位与通信信号独立

7.2 信号变化的级联效应

NTN信号等级变化
    ├──► SatelliteController 缓存更新
    │       ├──► INtnSignalStrengthCallback 通知(应用层)
    │       ├──► TelephonyRegistry 广播(系统服务层)
    │       │       ├──► SystemUI 更新图标
    │       │       ├──► ConnectivityService 调整网络评分
    │       │       └──► 其他注册的 TelephonyCallback
    │       └──► SatelliteSessionController 状态评估
    │               ├──► 信号丢失 → 可能触发会话结束
    │               └──► 信号恢复 → 可能触发重新连接
    ├──► SessionMetricsStats 统计更新
    │       └──► 最大信号等级记录
    └──► CarrierRoamingSatelliteSessionStats
            └──► 信号等级变化日志

7.3 关键边界条件

  1. 卫星模式未启用handleCmdUpdateNtnSignalStrengthReporting() 会忽略信号上报请求

  2. Demo 模式 vs 真实模式notifyResultIfExpectedListener() 确保两种模式的信号不会混淆

  3. Carrier Roaming NTN Feature FlagmFeatureFlags.carrierRoamingNbIotNtn() 控制运营商NTN路径是否启用

  4. 多 SIM 场景:信号强度按 subId 维度管理,mLastNotifiedCarrierRoamingNtnSignalStrengthSparseArray<NtnSignalStrength>

toolName: todo_write

status: success

Todos updated: 6 items

以上就是基于 Android 16 AOSP 源码的完整分析。核心发现总结:

  1. 双路径架构:OEM 卫星模式走 ISatellite HAL → SatelliteService → ISatelliteListener 专用通道;运营商 NTN 漫游模式走 IRadio AIDL → RILJ → SignalStrengthController 标准 3GPP 通道,两条路径在 SatelliteController 汇聚。

  2. 事件驱动上报:Modem 仅在 signalStrengthLevel 变化时上报,而非周期轮询。Framework 通过 DeviceStateMonitor 动态控制上报启停(屏幕关闭时停止上报以省电)。

  3. 三级防抖机制:① Modem 侧等级变化门限过滤;② Framework 侧 updateLastNotifiedCarrierRoamingNtnSignalStrengthAndNotify() 的 Level 比较去重;③ 连接断开滞后定时器(Hysteresis Timer)防止信号短暂中断导致的频繁切换。

  4. 5级离散信号模型:卫星信号采用 0-4 的离散等级(NONE/LOW/MEDIUM/HIGH/GOOD),而非蜂窝网络的连续 RSSI/RSRP 值,厂商在 SatelliteService 中负责原始测量值到标准等级的映射。