一、总体流程概览
Android 16 中卫星信号变化通知存在 两条并行路径,分别服务于不同的卫星通信模式:
| 路径 | 模式 | 触发源 | 通知链路 |
|---|---|---|---|
| 路径A:OEM卫星模式 | 独立卫星(如SOS紧急通信) | ISatellite HAL → SatelliteService | ISatelliteListener.onNtnSignalStrengthChanged() |
| 路径B:运营商NTN漫游模式 | Carrier Roaming NB-IoT NTN | IRadio AIDL → RILJ → Phone | SignalStrengthController → 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()
│ │
│ ▼
│ DefaultPhoneNotifier → TelephonyRegistryManager
│ │
│ [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 │
│ │ ▼
│ ▼ TelephonyRegistryManager
│ updateLastNotifiedCarrierRoaming │
│ 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 是厂商实现的系统服务,运行在独立进程中。它负责:
- 解析 Modem 原始数据:将厂商私有协议(QMI/AT等)的卫星信号数据解析为 Android 定义的
stub.NtnSignalStrength - 通过 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_REPORTING
→ handleCmdUpdateNtnSignalStrengthReporting(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 通过以下方式感知卫星信号变化:
- TelephonyRegistry 监听:注册
TelephonyCallback监听信号强度变化 - NetworkAgent 评分调整:卫星网络通过
TelephonyNetworkAgent上报网络质量,ConnectivityService 根据信号强度调整卫星网络的NetworkScore - 网络有效性判断:当卫星信号等级为
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 值 | 常量 | 图标显示 |
|---|---|---|
| 0 | NTN_SIGNAL_STRENGTH_NONE | 无信号/卫星图标灰色 |
| 1 | NTN_SIGNAL_STRENGTH_LOW | 1格信号 |
| 2 | NTN_SIGNAL_STRENGTH_MEDIUM | 2格信号 |
| 3 | NTN_SIGNAL_STRENGTH_HIGH | 3格信号 |
| 4 | NTN_SIGNAL_STRENGTH_GOOD | 4格信号/满格 |
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 D2D | NR NTN,3GPP标准 | IRadio AIDL | 通过标准SignalStrength |
| T-Mobile NTN | NB-IoT NTN | IRadio 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 交互矩阵
| 模块 | 交互方式 | 信号相关行为 |
|---|---|---|
| ConnectivityService | TelephonyNetworkAgent | 根据信号等级调整网络评分 |
| SystemUI | TelephonyCallback | 显示卫星信号图标 |
| SatelliteManager | INtnSignalStrengthCallback | 应用层信号变化回调 |
| DeviceStateMonitor | RegistrantList | 控制信号上报启停 |
| SignalStrengthController | Registrant | 蜂窝信号变化触发卫星信号更新 |
| SatelliteSessionController | 状态机转换 | 信号变化影响会话状态 |
| WifiService | 无直接交互 | 不关心卫星信号 |
| LocationManager | GNSS HAL | 卫星定位与通信信号独立 |
7.2 信号变化的级联效应
NTN信号等级变化
├──► SatelliteController 缓存更新
│ ├──► INtnSignalStrengthCallback 通知(应用层)
│ ├──► TelephonyRegistry 广播(系统服务层)
│ │ ├──► SystemUI 更新图标
│ │ ├──► ConnectivityService 调整网络评分
│ │ └──► 其他注册的 TelephonyCallback
│ └──► SatelliteSessionController 状态评估
│ ├──► 信号丢失 → 可能触发会话结束
│ └──► 信号恢复 → 可能触发重新连接
├──► SessionMetricsStats 统计更新
│ └──► 最大信号等级记录
└──► CarrierRoamingSatelliteSessionStats
└──► 信号等级变化日志
7.3 关键边界条件
-
卫星模式未启用:
handleCmdUpdateNtnSignalStrengthReporting()会忽略信号上报请求 -
Demo 模式 vs 真实模式:
notifyResultIfExpectedListener()确保两种模式的信号不会混淆 -
Carrier Roaming NTN Feature Flag:
mFeatureFlags.carrierRoamingNbIotNtn()控制运营商NTN路径是否启用 -
多 SIM 场景:信号强度按
subId维度管理,mLastNotifiedCarrierRoamingNtnSignalStrength是SparseArray<NtnSignalStrength>
toolName: todo_write
status: success
Todos updated: 6 items
以上就是基于 Android 16 AOSP 源码的完整分析。核心发现总结:
-
双路径架构:OEM 卫星模式走
ISatellite HAL → SatelliteService → ISatelliteListener专用通道;运营商 NTN 漫游模式走IRadio AIDL → RILJ → SignalStrengthController标准 3GPP 通道,两条路径在SatelliteController汇聚。 -
事件驱动上报:Modem 仅在
signalStrengthLevel变化时上报,而非周期轮询。Framework 通过DeviceStateMonitor动态控制上报启停(屏幕关闭时停止上报以省电)。 -
三级防抖机制:① Modem 侧等级变化门限过滤;② Framework 侧
updateLastNotifiedCarrierRoamingNtnSignalStrengthAndNotify()的 Level 比较去重;③ 连接断开滞后定时器(Hysteresis Timer)防止信号短暂中断导致的频繁切换。 -
5级离散信号模型:卫星信号采用 0-4 的离散等级(NONE/LOW/MEDIUM/HIGH/GOOD),而非蜂窝网络的连续 RSSI/RSRP 值,厂商在 SatelliteService 中负责原始测量值到标准等级的映射。