一、总体结论
Kylin 在 Android 13 上的卫星通信移植是一套面向中国星网的全业务定制方案,以 TelephonyManager XW扩展(~750行@hide方法)+ 独立 XwosTeleService 进程(5个子服务)+ 私有 IXwRadio/IXwRadioVoice HAL 的三层架构,实现了语音通话、数据业务、位置上报、通话统计等完整功能。Android 16 AOSP 以 SatelliteManager 公开API + SatelliteController/SatelliteSessionController 9态状态机 + DatagramController/Dispatcher/Receiver 消息三件套 + 标准化 ISatellite HAL 的模块化架构,聚焦紧急SOS消息和低带宽数据报传输,并深度集成NTN信号上报、地面/卫星智能切换、TRANSPORT_SATELLITE 数据连接、运行时配置管理、全链路Metrics等能力。
核心差异:Kylin 功能更全(语音/数据/位置/统计/安全/自定义扩展)但架构封闭、无状态机、无 消息队列 重试机制; AOSP 架构开放、9态状态机严谨、消息流程完整、功耗管理精细但仅支持 窄带 消息场景。
在流量统计维度上:Android 16 已在 NetworkStatsService/NetworkTemplate/NetworkIdentity 中搭建了卫星流量识别的基础架构——通过 mTransportTypesBits 中的 TRANSPORT_SATELLITE 位区分卫星流量,通过 NetworkTemplate.Builder.setTransportType() 构建卫星专用查询模板,getMobileUidStats() 合并统计蜂窝与卫星流量——但尚无独立的卫星流量统计 API 或专属统计策略。Kylin Android 13 则完全缺失卫星流量统计能力,NetworkIdentity 不含 TRANSPORT_SATELLITE 位,NetworkTemplate 无法按传输类型匹配,卫星流量会被混入移动网络流量中无法单独计量。
最关键优化方向:引入 SatelliteManager 适配层、实现 SatelliteSessionController 状态机、补充 Datagram 消息队列与重试机制、HAL 接口标准化、补充紧急SOS功能、增加卫星流量统计支持。
二、架构对比
2.1 分层设计对比
┌──────────────────────────────────────────────────────────────────────────────┐
│ Android 16 AOSP 卫星通信架构 │
├──────────────────────────────────────────────────────────────────────────────┤
│ 应用层: Emergency SOS App / Gateway App(Messages) / Satellite Hub │
│ ↓ Context.SATELLITE_SERVICE │
│ API层: SatelliteManager (公开SDK, 部分SystemApi) │
│ ├── SatelliteCapabilities (能力查询, 运行时动态) │
│ ├── SatelliteDatagram (数据报封装) │
│ ├── NtnSignalStrength (NTN信号强度, 5级离散模型) │
│ ├── SatelliteSubscriberProvisionStatus (订阅状态) │
│ ├── AntennaPosition / PointingInfo / SatelliteInfo │
│ └── SatelliteManager.SatelliteModemState (9态注解) │
│ ↓ ITelephony [Binder] │
│ 服务层: SatelliteController (com.android.phone进程, 90+消息类型) │
│ ├── SatelliteSessionController (9态状态机) │
│ │ UnavailableState / PowerOffState / EnablingState │
│ │ DisablingState / IdleState / TransferringState │
│ │ ListeningState / NotConnectedState / ConnectedState │
│ ├── DatagramController → DatagramDispatcher → DatagramReceiver │
│ │ (LinkedHashMap双优先级队列 + 重试 + MT轮询 + 节流) │
│ ├── SatelliteModemInterface (HAL交互, ExponentialBackoff重连) │
│ ├── PointingAppController (对星UI, 全屏/小窗口) │
│ ├── SatelliteSOSMessageRecommender (紧急SOS推荐, T911/SOS双模式) │
│ ├── NtnCapabilityResolver (NTN能力解析, PLMN匹配+服务类型) │
│ ├── SatelliteConfigParser (配置解析, protobuf格式) │
│ ├── SatelliteOptimizedApplicationsTracker (优化App追踪) │
│ ├── DemoSimulator (Demo模式独立状态机) │
│ ├── SatelliteServiceUtils (类型转换工具) │
│ ├── SatelliteConstants (常量/注解定义) │
│ ├── SatelliteConfig (配置管理) │
│ └── Metrics体系 (7个类): │
│ ControllerMetricsStats / SessionMetricsStats │
│ ProvisionMetricsStats / EntitlementMetricsStats │
│ CarrierRoamingSatelliteSessionStats │
│ CarrierRoamingSatelliteControllerStats │
│ AccessControllerMetricsStats │
│ ↓ ISatellite AIDL [Binder] │
│ HAL层: ISatellite.aidl + ISatelliteListener.aidl (标准化HAL) │
│ ├── SatelliteImplBase (厂商抽象基类, 零默认实现) │
│ ├── requestSatelliteMode() / sendSatelliteDatagram() │
│ ├── pollPendingDatagrams() / setSatellitePlmn() │
│ └── onNtnSignalStrengthChanged / onPendingDatagrams / ... │
│ ↓ │
│ Connectivity层: SatelliteAccessController (packages/modules/Connectivity) │
│ ├── 卫星网络访问权限管理 │
│ ├── requestIsCommunicationAllowedForCurrentLocation() │
│ └── updateSystemSelectionChannels() │
│ ↓ │
│ 数据路径: ConnectivityManager.requestNetwork(TRANSPORT_SATELLITE) │
│ → ConnectivityService → TelephonyNetworkProvider │
│ → DataNetworkController → DataServiceManager → IRadioData │
│ → Modem setupDataCall → NetworkAgent注册 │
│ ↓ │
│ 流量统计层: NetworkStatsService (packages/modules/Connectivity) │
│ ├── 卫星接口被识别为移动网络(isMobile含TRANSPORT_SATELLITE) │
│ ├── mAllMobileIfacesSinceBoot 集合包含卫星接口 │
│ ├── NetworkIdentity.mTransportTypesBits 含 TRANSPORT_SATELLITE 位 │
│ ├── NetworkTemplate.Builder.setTransportType(TRANSPORT_SATELLITE) │
│ │ 可构建卫星专用查询模板(受FLAG_NETSTATS_TRANSPORT_TYPE控制) │
│ ├── getMobileUidStats() 合并统计蜂窝+卫星流量 │
│ ├── 卫星网络标记为metered(NET_CAPABILITY_NOT_METERED缺失) │
│ └── 底层: eBPF数据采集(已完全替代xt_qtaguid) │
│ ├── TrafficStats: 无卫星相关API变更, JNI读取eBPF │
│ ├── NetworkStatsFactory: 从eBPF maps读取, 不感知传输类型 │
│ └── 卫星流量与蜂窝共享同一套eBPF管道, 区分依赖上层匹配 │
│ ↓ │
│ Modem: 3GPP NTN 协议栈 (NB-IoT NTN / NR NTN / eMTC NTN / Proprietary) │
└──────────────────────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────────────────────┐
│ Kylin Android 13 XWOS 卫星通信架构 │
├──────────────────────────────────────────────────────────────────────────────┤
│ 应用层: 星网定制App / Settings扩展(ProcessorInfoPreferenceController) │
│ ↓ TelephonyManager.getXw...() / XwTelephonyManager │
│ API层: TelephonyManager XW扩展方法 (全部@hide, L17086-L17844, ~750行) │
│ + XwTelephonyManager (vendor封装) │
│ ├── XwCallStateListener (通话状态监听) │
│ ├── CustomEventListener (自定义事件监听) │
│ ├── CustomRequestCallback (自定义请求回调) │
│ └── CallState (Parcelable通话状态, dir/stat/mode/rate全为int) │
│ ↓ ITelephony.aidl [Binder] (16个XW扩展方法) │
│ 服务层: PhoneInterfaceManager (com.android.phone进程) │
│ ├── XWRadioState (int, L420) + mXWSlotId + mIsXWRadioState │
│ └── XwRadioReceiver (BroadcastReceiver, L12334) │
│ + XwosTeleService (独立进程: com.starkylin.xwos.teleservice) │
│ ├── TeleVoiceService → RadioVoiceConnection (语音HAL交互) │
│ ├── TeleDataService → TRANSPORT_SATELLITE + ApnServer │
│ ├── TeleLocationService → LocationManager │
│ ├── TeleStatsService → Room数据库 (主叫/被叫/掉话/单双通) │
│ └── AudioStreamer → JNI (语音编解码, 共享内存) │
│ ↓ IXwRadio.aidl / IXwRadioVoice.aidl [Binder] │
│ HAL层: vendor.xwos.hardware.radio.* (私有HAL AIDL) │
│ ├── IXwRadio: setRadioPowerXW/dialXW/getPostimeXW/... │
│ ├── IXwRadioVoice: sendUplinkVoiceData/acquireVoiceDataBuffer/... │
│ └── IXwRadioIndication: xwRadioStateChanged/callStateChanged/... │
│ ↓ │
│ RIL层: vendor/cnt/RilXW (私有RIL实现 + mock模式) │
│ ├── RIL_XW_REQUEST_BASE = 80000 (18个请求码) │
│ └── RIL_XW_UNSOL_RESPONSE_BASE = 90000 (5个主动上报码) │
│ ↓ │
│ 数据路径: TeleDataService监听TRANSPORT_SATELLITE网络 │
│ → ApnServer管理卫星APN → DataNetwork添加TRANSPORT_SATELLITE │
│ → ConnectivityService → 卫星数据连接建立 │
│ ↓ │
│ 流量统计层: 无卫星流量统计支持 │
│ ├── NetworkIdentity 使用 mType(int) 而非 mTransportTypesBits(long) │
│ ├── NetworkTemplate 无 MATCH_ALL/setTransportType,仅支持传统规则 │
│ ├── getMobileUidStats() 已存在但不包含卫星流量 │
│ │ (isMobile仅含TRANSPORT_CELLULAR,卫星接口不在mAllMobileIfaces) │
│ ├── getUidStatsForTransport(TRANSPORT_SATELLITE) 会抛出异常 │
│ ├── 卫星流量混入移动网络流量,无法单独计量 │
│ └── 底层: eBPF/xt_qtaguid采集(Android 13仍使用xt_qtaguid) │
│ ├── TrafficStats: 无卫星相关API │
│ └── NetworkStatsFactory: 不感知传输类型, 卫星流量混入移动统计 │
│ ↓ │
│ CP: 星网卫星通信处理器 (高轨/低轨双模) │
└──────────────────────────────────────────────────────────────────────────────┘
2.2 关键架构差异
| 维度 | Android 16 AOSP | Kylin Android 13 | 影响 |
|---|---|---|---|
| API入口 | SatelliteManager(公开SDK,Context.SATELLITE_SERVICE) | TelephonyManager XW扩展(@hide,~750行)+ XwTelephonyManager | AOSP可被第三方App调用;Kylin仅系统App可用 |
| 服务进程 | Phone进程内(SatelliteController) | Phone进程 + 独立XwosTeleService进程 | Kylin双进程架构增加复杂度但隔离性好 |
| 状态机 | SatelliteSessionController 9态严格状态机 | XwRadioState 6枚举值,无状态机类 | AOSP状态转换有守卫;Kylin状态转换无约束 |
| 消息机制 | DatagramDispatcher + LinkedHashMap双优先级队列 + 重试 + 超时 + MT轮询节流 | 无消息队列,语音数据直接透传HAL | AOSP有可靠消息投递;Kylin无重试机制 |
| HAL接口 | ISatellite 标准HAL + SatelliteImplBase 抽象基类 | IXwRadio/IXwRadioVoice 私有HAL(全业务) | Kylin无法兼容其他卫星星座 |
| 数据连接 | TRANSPORT_SATELLITE + 标准DataCall 7阶段框架 | TRANSPORT_SATELLITE + ApnServer私有APN管理 | 两者均使用TRANSPORT_SATELLITE;AOSP走标准DataCall框架;Kylin通过ApnServer私有APN管理 |
| 信号上报 | 双路径:OEM卫星模式 + 运营商NTN漫游模式,5级离散模型+滞后滤波 | 仅通过customRequest(RSSI/SNR)主动查询 | AOSP信号上报体系完整 |
| 网络切换 | onTerrestrialNetworkAvailableChanged + 自动/手动 + 并发地面扫描 | 无自动切换 | AOSP支持智能地面/卫星切换 |
| 对星UI | PointingAppController 独立管理 + 全屏/小窗口对星 | 无对星引导 | AOSP有完整对星体验 |
| 权限模型 | USE_SATELLITE权限 + 系统弹窗告知收费 | 无独立卫星权限 | AOSP隐私保护更完善 |
| 配置管理 | SatelliteConfigParser(protobuf) + CarrierConfigManager(按PLMN) + SatelliteNetworkInfo(PLMN+服务策略+计费) | XWRadioConstants编译时固定常量 | AOSP运行时动态配置;Kylin编译时固定 |
| 可观测性 | 7个Metrics类 + PersistentLogger + SatelliteStats | TeleStatsService(Room数据库,仅通话统计) | AOSP全链路可观测;Kylin仅通话统计 |
| NTN能力解析 | NtnCapabilityResolver(PLMN匹配+服务类型自动识别) | 无 | AOSP自动识别NTN网络能力 |
| 优化App追踪 | SatelliteOptimizedApplicationsTracker(PROPERTY_SATELLITE_DATA_OPTIMIZED) | 无 | AOSP区分卫星优化/非优化App |
| Demo模式 | DemoSimulator独立状态机(PowerOff→NotConnected→Connected) + Mock Modem | isRilMockEnabled RIL mock | AOSP更完善的测试框架 |
| 功耗管理 | 灭屏30s超时 + 分级会话超时(180s/600s) + 干扰源自动禁用 + 并发地面扫描 | 无功耗管理策略 | AOSP远优于Kylin |
| 代码侵入 | 零侵入,独立模块 | 修改TelephonyManager(+750行)、ITelephony.aidl(+16方法)、RIL.java(+XW请求)、PhoneInterfaceManager(+XW实现)、DataNetwork.java(+TRANSPORT_SATELLITE) | AOSP远优于Kylin |
| 卫星流量统计 | NetworkStatsService识别卫星为移动网络变体 + NetworkTemplate.Builder.setTransportType(TRANSPORT_SATELLITE) 可构建卫星专用查询模板 + getMobileUidStats() 合并统计 | 无卫星流量统计支持:NetworkIdentity 使用 mType(int) 而非 mTransportTypesBits(long),NetworkTemplate 无 MATCH_ALL/setTransportType(),getMobileUidStats() 已存在但不包含卫星流量(isMobile 仅含 TRANSPORT_CELLULAR),getUidStatsForTransport(TRANSPORT_SATELLITE) 会抛异常 | AOSP有基础识别架构(但无独立API);Kylin完全缺失 |
2.3 核心类映射关系
| Android 16 AOSP | 职责 | Kylin Android 13 对应 | 差异 |
|---|---|---|---|
| SatelliteManager | 公开API入口 | TelephonyManager XW方法 + XwTelephonyManager | AOSP公开SDK;Kylin @hide |
| SatelliteController | 卫星服务总控(90+消息) | PhoneInterfaceManager XW部分 | AOSP专类专责;Kylin混在PIM |
| SatelliteSessionController | 9态状态机 | 无对应类(仅XwRadioState枚举) | Kylin缺失状态机 |
| DatagramController | 数据报收发控制 | 无对应类 | Kylin无消息队列 |
| DatagramDispatcher | 发送队列+重试+MT轮询 | 无对应类 | Kylin无重试机制 |
| DatagramReceiver | 接收轮询+SMS写入Provider | 无对应类 | Kylin无消息拉取 |
| SatelliteModemInterface | HAL交互+指数退避重连(2s→64s) | RadioVoiceConnection(仅语音HAL) | Kylin仅封装语音HAL |
| SatelliteSOSMessageRecommender | 紧急SOS推荐(T911/SOS) | 无对应类 | Kylin缺失 |
| PointingAppController | 对星UI管理(全屏/小窗口) | 无对应类 | Kylin缺失 |
| SatelliteAccessController | 接入权限控制 | 无对应类 | Kylin缺失 |
| NtnCapabilityResolver | NTN能力解析(PLMN匹配) | 无对应类 | Kylin缺失 |
| SatelliteConfigParser | protobuf配置解析 | 无对应类 | Kylin缺失 |
| SatelliteOptimizedApplicationsTracker | 优化App追踪 | 无对应类 | Kylin缺失 |
| DemoSimulator | Demo模式状态机 | isRilMockEnabled | AOSP更完善 |
| SatelliteServiceUtils | 类型转换工具 | 无对应类 | Kylin缺失 |
| SatelliteConstants | 常量/注解定义 | XWRadioConstants(编译时常量) | AOSP运行时注解;Kylin编译时固定 |
| SatelliteConfig | 配置管理 | 无对应类 | Kylin缺失 |
| SatelliteNetworkInfo | PLMN+服务策略+计费模型 | 无对应类 | Kylin缺失 |
| NetworkStatsService | 流量统计服务(含卫星识别) | NetworkStatsService(isMobile仅含CELLULAR,卫星接口不在mAllMobileIfacesSinceBoot) | AOSP识别卫星为移动网络变体;Kylin不识别卫星接口 |
| NetworkTemplate.Builder | 流量查询模板构建(含setTransportType) | NetworkTemplate.Builder(无setTransportType,需@TemplateMatchRule参数) | AOSP可构建卫星专用查询模板;Kylin无此能力 |
| NetworkIdentity | 网络身份识别(含mTransportTypesBits+TRANSPORT_SATELLITE位) | NetworkIdentity(使用mType(int)而非mTransportTypesBits(long),无TRANSPORT_SATELLITE) | AOSP通过mTransportTypesBits区分卫星;Kylin无法区分 |
| TrafficStats | 流量统计工具类(无卫星相关变更) | TrafficStats(无变更) | 两者均无卫星相关API;底层均通过eBPF采集 |
| NetworkStatsFactory | 底层统计数据采集(无卫星相关变更) | NetworkStatsFactory(无变更) | 两者底层均从eBPF maps读取,不感知传输类型 |
| ISatellite HAL | 标准化HAL接口 | IXwRadio + IXwRadioVoice | 接口设计理念不同 |
| ISatelliteListener | HAL事件回调 | IXwRadioIndication + IXwRadioVoiceIndication | AOSP事件语义更清晰 |
| SatelliteCapabilities | 能力查询(运行时) | XWRadioConstants(编译时常量) | AOSP运行时查询;Kylin编译时固定 |
| Metrics (7个类) | 全链路可观测性 | TeleStatsService(仅通话统计) | AOSP更全面 |
| — | 语音通话 | TeleVoiceService + AudioStreamer | Kylin独有 |
| — | 位置上报 | TeleLocationService | Kylin独有 |
| — | 通话统计 | TeleStatsService(Room数据库) | Kylin独有 |
| — | APN管理 | ApnServer | Kylin独有 |
| — | TRANSPORT_SATELLITE数据网络 | DataNetwork.java(添加TRANSPORT_SATELLITE支持) | Kylin独有修改,AOSP原生已包含 |
| — | 语音编解码 | AudioStreamer(JNI+共享内存) | Kylin独有 |
| — | 安全卡 | getSectfXw() | Kylin独有 |
| — | 摇晕摇毙 | executeStunXw/executeKillXw | Kylin独有 |
| — | 载波模式 | setCarrierMode/getCarrierMode | Kylin独有 |
| — | 自定义扩展 | customRequest()(107个ID) + ICustomEventListener | Kylin独有 |
三、功能对比表
| 功能领域 | Android 16 AOSP | Kylin Android 13 | 差异说明 |
|---|---|---|---|
| 卫星模式开关 | requestSatelliteEnabled() + 9态状态机 + 冲突无线电禁用(BT/WiFi/NFC/UWB) | setRadioPowerXw() 直接控制CP | AOSP有完整状态机+自动禁用干扰源;Kylin直接开关CP |
| 紧急SOS消息 | 核心功能,DATAGRAM_TYPE_SOS_MESSAGE + SatelliteSOSMessageRecommender + T911/SOS双模式 + ESOS Profile | 无独立SOS接口 | AOSP首要场景;Kylin未实现 |
| 卫星短消息 | sendDatagram() + 队列+重试+超时+MT轮询节流 | 无公开SMS接口 | AOSP完整消息流程;Kylin缺失 |
| 消息接收 | pollPendingDatagrams() 拉取模式 + SMS写入Provider + SharedPreferences去重 | 无消息接收机制 | AOSP有存储转发;Kylin缺失 |
| 卫星语音通话 | 明确不支持(NB-NTN窄带设计) | dialXw() + IXwRadioVoice HAL + AudioStreamer JNI | Kylin独有,800bps/2.4kbps/4.8kbps |
| 语音编解码 | 不支持 | AudioStreamer JNI + 共享内存 | Kylin独有 |
| 卫星数据业务 | TRANSPORT_SATELLITE + 标准DataCall 7阶段 + 卫星网络标记为metered(NET_CAPABILITY_NOT_METERED缺失) | TRANSPORT_SATELLITE + TeleDataService + ApnServer | 两者均使用TRANSPORT_SATELLITE;AOSP走标准DataCall框架且卫星网络标记为metered;Kylin通过ApnServer私有APN管理,DataNetwork.java已添加TRANSPORT_SATELLITE支持 |
| 位置上报 | 位置共享(SOS场景,Datagram承载)+ startSatellitePositionUpdates | TeleLocationService + PosTime | Kylin更完整(GNSS/ECEF/时间同步/距离阈值) |
| 信号强度查询 | 双路径信号上报(OEM+NTN漫游)+ 5级离散模型 + 滞后滤波 + 上报频率控制 | 仅通过customRequest(RSSI/SNR)主动查询 | AOSP体系完整;Kylin缺少独立API |
| 地面/卫星切换 | onTerrestrialNetworkAvailableChanged + 自动切换 + 并发地面扫描 | 无自动切换 | AOSP独有 |
| 对星引导 | PointingAppController + 全屏/小窗口对星UI + AntennaPosition | 无对星引导 | AOSP独有 |
| 权限控制 | USE_SATELLITE权限 + 系统弹窗 | 无独立卫星权限 | AOSP独有 |
| 卫星流量统计 | 基础支持:NetworkTemplate.Builder.setTransportType(TRANSPORT_SATELLITE) 可构建卫星专用查询模板(受Feature Flag控制),getMobileUidStats() 合并统计蜂窝+卫星流量,NetworkStatsService 将卫星接口识别为移动网络变体;无独立API(无 getSatelliteUidStats() / querySummaryForSatellite()),无专属统计策略 | 完全缺失:NetworkIdentity 不含 TRANSPORT_SATELLITE 位(使用 mType 而非 mTransportTypesBits),NetworkTemplate 无法按传输类型匹配(无 MATCH_ALL/setTransportType()),getMobileUidStats() 已存在但不包含卫星流量(isMobile 仅含 TRANSPORT_CELLULAR,卫星接口不在 mAllMobileIfacesSinceBoot 中),getUidStatsForTransport(TRANSPORT_SATELLITE) 会抛出异常,卫星流量混入移动网络流量无法单独计量 | AOSP有基础识别架构但尚不完整;Kylin完全缺失,用户/应用无法精确计量卫星数据消耗 |
| 流量计费属性 | 卫星网络标记为metered(NET_CAPABILITY_NOT_METERED缺失),系统可区分计费/非计费网络 | 无卫星流量计费属性管理 | AOSP支持计费感知;Kylin无此能力 |
| 卫星流量调试 | adb shell dumpsys netstats 输出包含卫星接口(在"All mobile interfaces"列表中);无 --satellite-stats 专用选项 | 无卫星流量调试支持 | AOSP有基础调试能力;Kylin无 |
| NTN能力解析 | NtnCapabilityResolver(PLMN匹配+服务类型自动识别) | 无 | AOSP独有 |
| 优化App追踪 | SatelliteOptimizedApplicationsTracker | 无 | AOSP独有 |
| 配置管理 | SatelliteConfigParser(protobuf) + CarrierConfigManager + SatelliteNetworkInfo | XWRadioConstants编译时固定 | AOSP运行时动态;Kylin编译时固定 |
| Demo/测试模式 | DemoSimulator独立状态机 + CTS + @VisibleForTesting | isRilMockEnabled RIL mock | AOSP更完善 |
| 功耗管理 | 灭屏30s超时 + 分级会话超时 + 干扰源自动禁用 + 并发地面扫描 | 无功耗管理 | AOSP远优于Kylin |
| 可观测性 | 7个Metrics类 + PersistentLogger + SatelliteStats | TeleStatsService(仅通话统计) | AOSP全链路可观测;Kylin仅通话统计 |
四、核心流程差异详解
4.1 卫星流量统计流程对比
Android 16 卫星流量统计机制
Android 16 在流量统计框架中为卫星通信搭建了基础识别架构,但尚未实现完整的卫星流量统计体系。核心流程如下:
1. 卫星流量识别
卫星网络注册 → ConnectivityService 创建 NetworkAgent(TRANSPORT_SATELLITE)
→ NetworkStatsService.handleNetworkStateChanged()
→ 判断 isMobile = (TRANSPORT_CELLULAR == displayTransport
|| TRANSPORT_SATELLITE == displayTransport)
→ 卫星接口添加到 mAllMobileIfacesSinceBoot 集合
→ NetworkIdentity.Builder 构建 mTransportTypesBits(含 TRANSPORT_SATELLITE 位)
→ 卫星流量在 legacy type 字段中被标记为 TYPE_MOBILE
关键代码路径:
-
NetworkStatsService.java:2357-2360 — isMobile 判断逻辑
-
NetworkStatsService.java:2472-2480 — getSubIdForCellularOrSatellite()
-
NetworkIdentity.java:75,99 — mTransportTypesBits 字段及 Builder 中的 setTransportTypes()
2. 卫星流量查询
应用构建查询模板:
NetworkTemplate template = new NetworkTemplate.Builder()
.setTransportType(NetworkCapabilities.TRANSPORT_SATELLITE) // 受 FLAG_NETSTATS_TRANSPORT_TYPE 控制
.build();
NetworkStatsManager.querySummaryForDevice(template, start, end);
→ INetworkStatsService.getNetworkStatsForTemplate(template)
→ NetworkIdentity.matchesTransportTypes() 匹配
→ 仅返回 mTransportTypesBits 包含 TRANSPORT_SATELLITE 的记录
3. getMobileUidStats() 行为
NetworkStatsManager.getMobileUidStats()
→ mService.getUidStatsForTransport(TRANSPORT_CELLULAR)
→ getAllIfacesSinceBoot(TRANSPORT_CELLULAR) 返回 mAllMobileIfacesSinceBoot
→ mAllMobileIfacesSinceBoot 包含卫星接口(因 isMobile 判断包含 TRANSPORT_SATELLITE)
→ 返回结果 = 蜂窝流量 + 卫星流量(合并统计)
注意:getMobileUidStats() 的文档明确声明返回"cellular and satellite"统计。目前没有 getUidStatsForTransport(TRANSPORT_SATELLITE) 的公开调用入口,但 AIDL 接口 INetworkStatsService.getUidStatsForTransport(int transport) 理论上支持传入 TRANSPORT_SATELLITE。
4. 统计策略
| 策略维度 | Android 16 卫星流量 |
|---|---|
| 轮询频率 | 与蜂窝相同,无独立策略 |
| 前台/后台区分 | 与蜂窝相同(SET_FOREGROUND/SET_DEFAULT) |
| 按波束/运营商统计 | 不支持 |
| 低功耗模式统计延迟 | 无特殊处理 |
| 计费标记 | 卫星网络标记为 metered(NET_CAPABILITY_NOT_METERED 缺失) |
| 流量阈值回调 | 不支持 |
5. 与卫星框架的集成
| 集成点 | 状态 | 说明 |
|---|---|---|
| SatelliteAccessController → NetworkStatsService | 无直接集成 | SAC 仅通过回调通知 ConnectivityService 更新网络偏好,不涉及流量统计 |
| SatelliteAccessController → 流量统计重置/标记 | 不存在 | 启用/禁用卫星网络时不通知 NetworkStatsService |
| ConnectivityService 卫星网络请求 → 流量统计 | 间接关联 | 卫星网络通过 TRANSPORT_SATELLITE 注册到 ConnectivityService,NetworkStatsService 通过网络状态快照感知 |
| 卫星消息字节数记录 | 不存在 | SatelliteController/DatagramDispatcher 中无流量统计调用 |
6. 调试支持
-
adb shell dumpsys netstats 输出中包含卫星接口(在"All mobile interfaces"列表中,mAllMobileIfacesSinceBoot 可见)
-
无 --satellite-stats 专用选项
-
无模拟卫星网络环境的测试钩子
7. 底层实现细节
| 组件 | 卫星相关变更 | 说明 |
|---|---|---|
| TrafficStats | 无卫星相关API变更 | 未新增卫星相关方法,底层仍通过JNI(framework-connectivity-tiramisu-jni)读取eBPF统计数据 |
| NetworkStatsFactory | 无卫星相关变更 | 底层仍从eBPF maps读取统计数据,不感知传输类型,卫星流量与蜂窝流量共享同一套eBPF管道 |
| NetworkStats.Bucket/NetworkStats.Entry | 无TYPE_SATELLITE常量 | 卫星流量通过NetworkIdentity.mTransportTypesBits区分,而非通过独立的网络类型字段 |
| eBPF数据采集 | 卫星流量与蜂窝共享同一套eBPF管道 | Android 16中eBPF已完全替代xt_qtaguid(xt_qtaguid已废弃),卫星流量的底层采集与蜂窝流量无差异,区分依赖于上层的NetworkIdentity匹配 |
| getSubIdForCellularOrSatellite() | 新增 | 同时处理蜂窝和卫星网络的订阅ID获取 |
| getRatTypeForStateSnapshot() | 扩展 | 同时检查TRANSPORT_CELLULAR和TRANSPORT_SATELLITE的RAT类型 |
关键发现:Android 16中没有 TYPE_SATELLITE 这样的独立网络类型常量。卫星网络在传统类型字段中仍被标记为 TYPE_MOBILE,但通过 NetworkIdentity.mTransportTypesBits 中的 TRANSPORT_SATELLITE 位进行区分。这意味着卫星流量被统计为移动网络流量的一部分,但可通过 NetworkTemplate.Builder().setTransportType(TRANSPORT_SATELLITE) 构建的模板专门匹配。
重要:MATCH_MOBILE 模板不会自动匹配卫星流量。matchesMobile() 仅匹配 TYPE_MOBILE + 特定 RAT 类型,不匹配 TRANSPORT_SATELLITE。要查询卫星流量,必须使用 NetworkTemplate.Builder().setTransportType(TRANSPORT_SATELLITE) 构建专用模板(受 FLAG_NETSTATS_TRANSPORT_TYPE Feature Flag 控制)。
Kylin Android 13 卫星流量统计现状
Kylin Android 13 完全缺失卫星流量统计能力:
1. 识别层缺失
-
NetworkIdentity 使用 mType(int,legacy type)而非 mTransportTypesBits(long,位字段),不包含 TRANSPORT_SATELLITE 位
-
NetworkTemplate 无法按传输类型匹配,仅支持 MATCH_MOBILE/MATCH_WIFI/MATCH_ETHERNET/MATCH_CARRIER 等传统规则,无 MATCH_ALL(12) 规则
-
NetworkTemplate.Builder 构造函数需要 @TemplateMatchRule matchRule 参数,无 setTransportType()
-
即使 TRANSPORT_SATELLITE 常量在 Android 13 API 33 中已定义,流量统计模块未使用该信息
2. API 层缺失
-
NetworkStatsManager.getMobileUidStats()已存在(Android 13 Tiramisu 模块中引入),但内部调用 getUidStatsForTransport(TRANSPORT_CELLULAR),而 getAllIfacesSinceBoot(TRANSPORT_CELLULAR) 返回 mAllMobileIfacesSinceBoot,该集合不包含卫星接口(因 isMobile 判断仅含 TRANSPORT_CELLULAR),因此 getMobileUidStats() 不包含卫星流量
-
INetworkStatsService.getUidStatsForTransport(int transport) 接口已存在,但 getAllIfacesSinceBoot() 仅支持 TRANSPORT_WIFI 和 TRANSPORT_CELLULAR,传入其他值(包括 TRANSPORT_SATELLITE)会抛出 IllegalArgumentException
-
NetworkTemplate.Builder 无 setTransportType(),Builder 构造函数需要 @TemplateMatchRule matchRule 参数,仅支持 MATCH_MOBILE/MATCH_WIFI/MATCH_ETHERNET/MATCH_CARRIER 等传统规则,无 MATCH_ALL(12) 规则
-
无任何卫星流量统计专用 API
3. 统计行为
-
卫星数据连接通过 TeleDataService 建立,使用 TRANSPORT_SATELLITE 传输类型
-
但 NetworkStatsService.handleNetworkStateChanged() 中 isMobile = (TRANSPORT_CELLULAR == displayTransport),不包含 TRANSPORT_SATELLITE,卫星接口不会被添加到 mAllMobileIfacesSinceBoot 集合
-
getMobileUidStats() 内部调用 getUidStatsForTransport(TRANSPORT_CELLULAR),返回 mAllMobileIfacesSinceBoot 中的接口统计,不包含卫星接口
-
getUidStatsForTransport(TRANSPORT_SATELLITE) 会抛出 IllegalArgumentException(getAllIfacesSinceBoot() 仅支持 TRANSPORT_WIFI 和 TRANSPORT_CELLULAR)
-
卫星流量可能被混入移动网络流量统计中(如果卫星接口的 legacy type 被标记为 TYPE_MOBILE),但无法单独提取
-
TeleStatsService 仅统计通话数据(主叫/被叫/掉话/单双通),不涉及数据流量统计
4. Kylin 移植中未涉及的流量统计修改
-
从代码分析推断,Kylin 移植未修改 NetworkStatsService、NetworkTemplate、NetworkIdentity 等流量统计相关类
-
TeleDataService 负责卫星数据连接建立,但未集成流量统计功能
对用户/应用的影响
| 影响维度 | Android 16 AOSP | Kylin Android 13 |
|---|---|---|
| 精确计量卫星数据消耗 | 可通过 NetworkTemplate.Builder.setTransportType(TRANSPORT_SATELLITE) 查询卫星专用流量,但需启用 Feature Flag | 无法精确计量,卫星流量混入移动流量 |
| 流量计费感知 | 卫星网络标记为 metered,系统设置可显示计费警告 | 无计费属性区分 |
| 应用流量管理 | 应用可通过 querySummaryForDevice() + 卫星模板查询,但无独立便捷 API | 应用无法获知卫星流量消耗 |
| 运营商计费对接 | getSubIdForCellularOrSatellite() 支持按订阅ID关联,但无按波束/运营商统计 | 无运营商计费对接能力 |
兼容性影响
-
旧应用查询行为:针对 Android 13 开发的应用使用 querySummaryForDevice(TYPE_MOBILE, ...) 时,在 Android 16 上不会自动包含卫星流量(因为 MATCH_MOBILE 规则仅匹配 TYPE_MOBILE + RAT 类型,不匹配 TRANSPORT_SATELLITE)。
-
卫星流量误归类风险:由于卫星网络在 legacy type 字段中被标记为 TYPE_MOBILE,如果底层 telephony 将卫星接口注册为移动网络,则使用 MATCH_MOBILE 模板的旧查询可能包含卫星流量。当前代码中 isMobile = (TRANSPORT_CELLULAR == displayTransport || TRANSPORT_SATELLITE == displayTransport) 确保了卫星接口被添加到 mAllMobileIfacesSinceBoot。
-
getMobileUidStats() 行为:该方法文档明确声明返回"cellular and satellite"统计,调用方需注意此合并行为。
-
Feature Flag 依赖:NetworkTemplate.Builder.setTransportType() 受 FLAG_NETSTATS_TRANSPORT_TYPE Feature Flag 控制,设备需确认已启用此 Flag 才能使用卫星专用查询模板。
-
OEM 适配要点:
-
内核/HAL层:确保卫星网络接口被正确注册到 TelephonyNetworkSpecifier 中,包含正确的 subscriptionId;卫星 Modem 需要通过 PhoneStateListener 上报 RAT 类型;eBPF 程序无需修改,卫星流量通过标准网络接口采集
-
Framework层:启用 FLAG_NETSTATS_TRANSPORT_TYPE Feature Flag 以支持基于传输类型的模板查询;在 getDisplayTransport() 实现中正确映射卫星传输类型;确保卫星网络的 NetworkCapabilities 包含 TRANSPORT_SATELLITE
-
流量统计区分:如需独立统计卫星流量,使用 NetworkTemplate.Builder().setTransportType(TRANSPORT_SATELLITE).build() 构建查询模板
-
4.2 公开 API 对比
Android 16 — SatelliteManager(公开 SDK API)
SatelliteManager sm = getSystemService(Context.SATELLITE_SERVICE);
sm.isSupported(); // 能力查询
sm.requestSatelliteEnabled(enabled, enableDemoMode, ...); // 开关卫星
sm.registerSatelliteStateChangeListener(executor, listener); // 状态监听
sm.sendDatagram(subId, datagramType, datagram, needPointingUI, ...); // 发送数据报
sm.registerSatelliteDatagramCallback(executor, callback); // 接收数据报
sm.requestSatelliteCapabilities(executor, callback); // 查询能力
sm.provisionSatelliteService(token, executor, callback); // 配置服务
sm.isSatelliteProvisioned(); // 配置状态
sm.isSatelliteEnabledForCurrentCarrier(); // 运营商支持
sm.startSatellitePositionUpdates(executor, callback); // 卫星位置更新
sm.requestSatelliteAccessConfigurationForCurrentLocation(...); // 接入配置
Kylin Android 13 — TelephonyManager XW 扩展(全部 @hide)
tm.setRadioPowerXw(true, executor, callback); // 开关CP
tm.dialXw(number, type, rate, executor, callback); // 卫星拨号
tm.getPostimeXwAsync(type, executor, receiver); // 获取位置时间
tm.customRequest(request, data, executor, callback); // 自定义请求(107个ID)
tm.registerCallStateListener(executor, listener); // 通话状态监听
tm.setCommunicationTypeXw(type, executor, callback); // 高低轨切换
tm.executeStunXwAsync(mode, value, executor, receiver); // 摇晕操作
tm.executeKillXwAsync(executor, receiver); // 摇毙操作
tm.getSectfXw(); // 安全卡(同步)
tm.setCarrierMode(mode, executor, callback); // 载波模式
tm.getSatellitePhoneId(); // 卫星Phone ID
关键差异:
| 对比项 | Android 16 | Kylin Android 13 |
|---|---|---|
| API 可见性 | 公开 SDK (Context.SATELLITE_SERVICE) | @hide,仅系统App |
| API 入口 | SatelliteManager 独立类 | TelephonyManager 扩展方法(~750行) |
| 功能范围 | 消息/状态/配置/能力查询/对星 | 语音/数据/位置/电源/安全/自定义 |
| 异步模式 | 统一 OutcomeReceiver | 混用 Consumer/ResultReceiver/AIDL回调 |
| 权限控制 | USE_SATELLITE + 系统弹窗 | 无独立权限 |
| 消息类型 | DATAGRAM_TYPE_SOS_MESSAGE/SMS/KEEP_ALIVE | 无消息类型概念 |
| 语音通话 | 不支持 | dialXw + ICallStateListener |
| 代码侵入 | 零侵入 | 修改ITelephony.aidl(+16方法) |
4.3 卫星模式开关状态机对比
Android 16 — SatelliteSessionController(9态严格状态机,源码确认):
UnavailableState ──(设备不支持)──→ 终态
│
PowerOffState ──requestSatelliteEnabled(true)──→ EnablingState
│
EVENT_SET_SATELLITE_ENABLED_DONE
│
┌────────────────┼────────────────┐
▼ ▼ ▼
IdleState NotConnectedState ConnectedState
(等待收发) (已注册未连接) (网络附着完成)
│ │
sendDatagram() onPendingDatagrams()
│ │
▼ ▼
TransferringState ←────────────────────────┘
│
发送完成,等待接收
▼
ListeningState (发送后180s/接收后30s分级超时)
│
超时或收到新数据
▼
IdleState
DisablingState ←── requestSatelliteEnabled(false) ←── 任何状态
│ (清理资源、解绑GatewayService、禁用干扰源恢复)
▼
PowerOffState
关键实现细节(源码确认):
-
ExponentialBackoff 处理绑定SatelliteService失败(2s→4s→8s→16s→32s→64s,上限64s)
-
灭屏30s自动进入省电模式(EVENT_SCREEN_OFF_TIMEOUT)
-
BT/WiFi/NFC/UWB自动禁用/恢复(EVENT_DISABLE_CONFLICTING_RADIO)
-
SatelliteModemEnableRequestAttributes 携带enableDemoMode/transportType/isCarrierRoaming
Kylin Android 13 — XwRadioState(6枚举值,无状态机类):
CLOSED ──setRadioPowerXw(true)──→ OPENNING (CP启动中,串口未ready)
│
串口就绪
│
▼
OPENED (CP已启动,串口已ready)
│
入网中
│
▼
CONNECTING (CP入网中)
│
数据业务建立
│
▼
CONNECED (CP已建立数据业务) ← 注意: 拼写错误
UNAVAILABLE (CP不可用)
关键差异:
| 对比项 | Android 16 | Kylin Android 13 |
|---|---|---|
| 状态机实现 | SatelliteSessionController 专用类,State模式,9个State内部类 | 无状态机类,仅6个枚举值 |
| 状态守卫 | enter()/exit() + 转换合法性检查 | 无守卫,任何状态可任意切换 |
| 超时处理 | ListeningState 180s/30s分级超时自动回Idle | 无超时机制 |
| 传输状态 | TransferringState/ListeningState 区分收发 | 无传输状态 |
| 错误状态 | UnavailableState + 错误处理和回退 | UNAVAILABLE枚举但无处理逻辑 |
| Connected含义 | 网络附着/注册完成,不分配IP | 数据业务已建立 |
| 禁用流程 | DisablingState 专门处理(清理资源、解绑GatewayService) | 直接关闭CP电源 |
| 指数退避 | ExponentialBackoff 处理绑定失败(2s→64s) | 无重连机制 |
| 屏幕感知 | 灭屏30s自动进入省电模式 | 无屏幕状态感知 |
| 干扰源管理 | 自动禁用/恢复BT/WiFi/NFC/UWB | 无干扰源管理 |
4.4 消息发送流程对比
Android 16 — 完整Datagram发送流程:
App: SatelliteManager.sendDatagram(SMS, datagram, true, callback)
│ [Binder IPC]
▼
SatelliteController.sendDatagram()
├── evaluateOemSatelliteRequestAllowed() → 权限检查
├── 若需对星: PointingAppController.startPointingUI()
▼
DatagramController.sendSatelliteDatagram()
▼
DatagramDispatcher.sendDatagram()
├── 排入发送队列 (LinkedHashMap<Long, DatagramItem>)
├── 紧急优先: mPendingEmergencyDatagramsMap > mPendingNonEmergencyDatagramsMap
├── CMD_SEND_SATELLITE_DATAGRAM (Handler消息)
▼
SatelliteModemInterface.sendSatelliteDatagram()
│ [Binder IPC]
▼
ISatellite.sendSatelliteDatagram(datagram, isEmergency, needPointingUI, callback)
│ [厂商RIL → Modem]
▼
Modem 通过卫星上行链路发送
▼
EVENT_SEND_SATELLITE_DATAGRAM_DONE
├── 成功:更新SendState → SEND_SUCCESS → 回调App
│ DatagramReceiver.pollPendingSatelliteDatagrams() (触发MT轮询)
└── 失败:保留在队列 → retrySendingDatagrams() → 超时: SATELLITE_RESULT_MODEM_TIMEOUT
MT SMS轮询流程:
DatagramReceiver
├── CMD_POLL_PENDING_SATELLITE_DATAGRAMS (节流: 最小间隔10s)
├── EVENT_POLL_PENDING_SATELLITE_DATAGRAMS_DONE
│ ├── 有新数据: 解析SatelliteDatagram → 写入SmsProvider → 通知App
│ └── 无新数据: 结束轮询
└── SharedPreferences记录datagramId去重
Kylin Android 13 — 无消息发送机制(语音通话流程):
App: TelephonyManager.dialXw(number, type, rate, callback)
│ [Binder IPC via ITelephony.aidl]
▼
ITelephony.dialXw() → PhoneInterfaceManager
│ [Binder IPC via IXwRadio.aidl]
▼
IXwRadio.dialXW(number, type, rate) → HAL
│
▼
RIL_XW_REQUEST_DIAL → CP
│
▼
IXwRadioIndication.callStateChanged() → ICallStateListener.onCallStateChanged()
语音数据通道:
AudioStreamer (JNI) ←→ 共享内存 ←→ IXwRadioVoice.sendUplinkVoiceData()
AudioStreamer (JNI) ←→ 共享内存 ←→ IXwRadioVoice.acquireVoiceDataBuffer()
关键差异:
-
AOSP有消息队列+重试+超时+紧急优先级;Kylin语音直接透传HAL,无队列无重试
-
AOSP有MT SMS轮询(节流控制+去重+写入SmsProvider);Kylin无消息接收
-
AOSP有Demo模式模拟(延迟发送、设备对齐模拟);Kylin仅有RIL mock
-
Kylin有语音数据通道(JNI+共享内存);AOSP无语音支持
4.5 信号上报流程对比
Android 16 — 双路径信号上报:
| 路径 | 模式 | 触发源 | 通知链路 |
|---|---|---|---|
| 路径A | OEM卫星模式 | ISatellite HAL → SatelliteService | ISatelliteListener.onNtnSignalStrengthChanged() → SatelliteModemInterface.VendorListener → SatelliteController → INtnSignalStrengthCallback + Phone.notifyCarrierRoamingNtnSignalStrengthChanged() → TelephonyRegistry → SystemUI/卫星应用/ConnectivityService |
| 路径B | Carrier NTN漫游 | IRadio AIDL → RILJ | RIL_UNSOL_SIGNAL_STRENGTH → SignalStrengthController → SatelliteController + Phone.notifySignalStrength() → TelephonyRegistry → 应用层 |
信号强度模型(5级离散化 + 滞后滤波):
NtnSignalStrength:
├── signalQuality: 0-4 (NONE/POOR/FAIR/GOOD/EXCELLENT)
├── signalStrength: 0-4
├── rssi: dBm值 (OEM卫星模式)
├── snr: dB值 (OEM卫星模式)
└── 滞后滤波: 防止信号等级频繁跳变
Kylin Android 13:
-
仅通过 customRequest(CUSTOM_REQUEST_GET_RSSI, ...) / customRequest(CUSTOM_REQUEST_GET_SNR, ...) 主动查询
-
无信号变化主动推送机制
-
无信号强度模型(5级离散化)、无滞后滤波、无上报频率控制
4.6 网络切换流程对比
Android 16:
地面网络恢复 → ISatelliteListener.onTerrestrialNetworkAvailableChanged(true)
→ SatelliteController → 评估是否应关闭卫星
├── 若CarrierConfig允许自动切换:
│ → requestSatelliteEnabled(false)
│ → SatelliteSessionController → DisablingState → PowerOffState
└── 若需手动确认:
→ 发送通知提示用户
并发地面扫描: IdleState中,若isConcurrentTnScanningSupported()为true,
Framework调用enableCellularModemWhileSatelliteModeIsOn(true)
→ 卫星模式运行期间保持地面Modem可用,地面网络恢复后快速切换
Kylin Android 13: 无自动切换机制,用户需手动开关卫星CP。
4.7 HAL 接口对比
Android 16 — ISatellite 标准HAL:
interface ISatellite {
void setSatelliteListener(ISatelliteListener listener);
void requestSatelliteEnabled(in SatelliteModemEnableRequestAttributes attributes,
IIntegerConsumer callback);
void requestSatelliteCapabilities(IIntegerConsumer callback);
void sendSatelliteDatagram(in SatelliteDatagram datagram, boolean isEmergency,
boolean needPointingUI, IIntegerConsumer callback);
void pollPendingDatagrams(IIntegerConsumer callback);
void startSendingSatellitePointingInfo(IIntegerConsumer callback);
void stopSendingSatellitePointingInfo(IIntegerConsumer callback);
void setSatellitePlmn(in List<String> plmnList, IIntegerConsumer callback);
}
interface ISatelliteListener {
void onSatelliteDatagramReceived(long datagramId, int count);
void onSatellitePositionChanged(in PointingInfo pointingInfo);
void onSatelliteModemStateChanged(int state);
void onNtnSignalStrengthChanged(in NtnSignalStrength signalStrength);
void onSatelliteCapabilitiesChanged(in SatelliteCapabilities capabilities);
void onPendingDatagrams(int count);
void onTerrestrialNetworkAvailableChanged(boolean isAvailable);
}
Kylin Android 13 — IXwRadio/IXwRadioVoice 私有HAL:
特点 :
- 接口定义完全由 XWOS 厂商控制 ,在 vendor.xwos.hardware.radio 包下
- 与 AOSP 标准 HAL 不兼容 ,无法直接复用 AOSP 的卫星框架
- 其他厂商无法直接复用 ,每个卫星厂商需要定义自己的私有 HAL
- 升级到新版本 Android 时可能需要重新适配 ,因为 AOSP 标准化接口可能变化
interface IXwRadio {
void setRadioPowerXW(boolean on, IBooleanConsumer callback);
void dialXW(String number, int type, int rate, IIntegerConsumer callback);
void hangupXW(IIntegerConsumer callback);
void answerXW(IIntegerConsumer callback);
void getPostimeXW(int type, IIntegerConsumer callback);
void setPostimeXW(int type, String data, IIntegerConsumer callback);
void getSectfXW(IIntegerConsumer callback);
void setSectfXW(String data, IIntegerConsumer callback);
void executeStunXW(int mode, int value, int timeout, IIntegerConsumer callback);
void executeKillXW(int timeout, IIntegerConsumer callback);
void setCommunicationTypeXW(int type, IBooleanConsumer callback);
void customRequest(int requestId, in byte[] data, ICustomRequestCallback callback);
}
interface IXwRadioVoice {
void sendUplinkVoiceData(in byte[] data);
byte[] acquireVoiceDataBuffer();
void releaseVoiceDataBuffer();
}
interface IXwRadioIndication {
void xwRadioStateChanged(int state);
void callStateChanged(in CallState callState);
void customEvent(int event, in byte[] data);
}
关键差异:
-
AOSP HAL 面向消息和状态,Kylin HAL 面向全业务(语音/数据/位置/安全/自定义)
-
AOSP 有地面网络可用性回调;Kylin 无此概念
-
AOSP 有卫星位置/对星信息回调;Kylin 无此概念
-
AOSP 有卫星能力动态回调;Kylin 无此概念
-
Kylin 有语音数据通道(
sendUplinkVoiceData/acquireVoiceDataBuffer);AOSP 无 -
Kylin 有自定义扩展接口(
customRequest/customEvent,107个ID);AOSP 无 -
AOSP 有SatelliteImplBase厂商抽象基类;Kylin 无抽象层
五、性能与功耗评估
| 指标 | Android 16 AOSP | Kylin Android 13 | 评价 |
|---|---|---|---|
| 内存 | ~200-400KB(24个类,40+原子变量,单例模式) | ~100-200KB(11个类+XwosTeleService独立进程) | AOSP内存略高但功能更完整;Kylin额外进程开销 |
| CPU | Handler消息驱动+MT轮询(节流)+Metrics计数器 | 无轮询,语音数据直接透传 | AOSP CPU略高但可控;Kylin语音JNI编解码有CPU峰值 |
| 功耗-灭屏 | 灭屏30s自动超时+NB-IoT不活动超时 | 无灭屏感知,CP可能长时间开启 | AOSP远优于Kylin |
| 功耗-会话 | P2P SMS 180s/ESOS 600s分级超时 | 无会话超时 | AOSP远优于Kylin |
| 功耗-干扰 | 自动禁用BT/WiFi/NFC/UWB | 无干扰源管理 | AOSP远优于Kylin |
| 功耗-地面扫描 | 并发地面扫描(避免反复开关卫星) | 不支持 | AOSP优于Kylin |
| 功耗-指数退避 | SatelliteService绑定失败2s→64s退避 | 无重连机制 | AOSP优于Kylin |
| 流量统计开销 | 需识别 TRANSPORT_SATELLITE 位,NetworkIdentity 匹配增加少量位运算开销;getMobileUidStats() 合并统计蜂窝+卫星接口,接口集合略大;整体CPU开销可忽略不计 | 无额外流量统计开销(因功能缺失) | AOSP有少量额外开销但可接受;Kylin零开销但功能缺失 |
| 响应时延-链路 | 状态机Enabling→Idle→Connected,5-15s | CP启动→入网→数据业务建立,10-30s | AOSP更快(状态机优化) |
| 响应时延-消息 | 3-10s(队列+重试+超时) | N/A(无消息功能) | AOSP独有 |
| 时延统计 | SessionMetricsStats全链路追踪 | TeleStatsService仅通话统计 | AOSP更全面 |
| 语音时延 | N/A | 800bps/2.4kbps/4.8kbps编解码,高延迟 | Kylin独有但延迟高 |
| 可观测性 | 7个Metrics类+PersistentLogger | TeleStatsService(仅通话) | AOSP远优于Kylin |
六、代码质量与可维护性分析
| 维度 | Android 16 AOSP | Kylin Android 13 | 评价 |
|---|---|---|---|
| 包结构 | android.telephony.satellite + com.android.internal.telephony.satellite + packages/modules/Connectivity | android.telephony.xwos + com.android.internal.telephony.xwos + vendor/xwos | AOSP标准化;Kylin厂商命名 |
| 代码侵入 | 零侵入,独立模块 | 修改TelephonyManager(+750行)、ITelephony.aidl(+16方法)、RIL.java(+XW请求)、PhoneInterfaceManager(+XW实现)、DataNetwork.java(+TRANSPORT_SATELLITE) | AOSP远优于Kylin |
| 设计模式 | 状态机(9态)+单例+观察者+Handler消息驱动+双优先级队列+指数退避+策略模式 | 过程式调用,无状态机,无队列 | AOSP远优于Kylin |
| 职责分离 | Controller/Dispatcher/Receiver/Metrics/PointingApp/ConfigParser/Resolver 分层清晰 | PhoneInterfaceManager承载所有XW方法+XwosTeleService 5个子服务 | AOSP更清晰 |
| 注释 | 完整Javadoc + @VisibleForTesting + @GuardedBy + @NonNull/@Nullable | 中文注释,缺少Javadoc标准格式 | AOSP更规范 |
| 类型安全 | @SatelliteManager.SatelliteModemState 注解 + 强类型数据类 | CallState字段全部为int,缺少@IntDef;customRequest(int, byte[])裸byte[] | AOSP远优于Kylin |
| 线程安全 | 40+ AtomicBoolean/AtomicInteger/AtomicLong,无锁并发 | sXwCallStateListeners(ConcurrentHashMap) vs sCustomEventListeners(HashMap+synchronized)风格不一致 | AOSP更一致 |
| Binder生命周期 | 完整IBinder.DeathRecipient处理 | registerCallStateListener有linkToDeath,registerForCustomEventListener无 | AOSP更完整 |
| 测试 | CTS + Demo模式 + Mock Modem + @VisibleForTesting | 无测试代码 | AOSP远优于Kylin |
| 升级影响 | 独立模块,Mainline APEX可独立更新 | 修改核心AIDL(ITelephony),影响所有Telephony客户端 | AOSP远优于Kylin |
| Vendor隔离 | SatelliteImplBase抽象基类,Framework无需修改 | Vendor代码直接修改AOSP核心文件 | AOSP远优于Kylin |
| 已知Bug | 无已知复制粘贴错误 | setPostimeXwAsync的catch日志写的是getPostimeXwAsync | Kylin有已知Bug |
| 进程架构 | 单进程(Phone),模块间直接调用 | 双进程(Phone+XwosTeleService),Binder跨进程通信 | AOSP更简单;Kylin隔离性更好 |
七、Android 13 移植的优化建议
高优先级
1. 引入状态机
-
问题: XwRadioState 仅为6个枚举值,无状态机类,无转换守卫,无超时处理
-
参考: Android 16 的 SatelliteSessionController 9态状态机
-
建议: 实现 XwSatelliteSessionController,至少包含 PowerOff→Enabling→Idle→Transferring→Listening→Disabling,添加
enter()/exit()守卫和转换合法性检查 -
收益: 解决状态不一致问题,支持超时/重试/异常恢复
-
实施:
-
public class XwSatelliteSessionController extends StateMachine { private final PowerOffState mPowerOffState = new PowerOffState(); private final EnablingState mEnablingState = new EnablingState(); private final IdleState mIdleState = new IdleState(); private final TransferringState mTransferringState = new TransferringState(); private final ListeningState mListeningState = new ListeningState(); private final DisablingState mDisablingState = new DisablingState(); class ListeningState extends State { private static final int TIMEOUT_MS = 180_000; @Override public void enter() { sendMessageDelayed(EVENT_TIMEOUT, TIMEOUT_MS); } @Override public boolean processMessage(Message msg) { if (msg.what == EVENT_TIMEOUT) { transitionTo(mIdleState); return HANDLED; } return NOT_HANDLED; } } }
-
2. 引入 SatelliteManager 适配层
-
问题: 所有卫星API挂在TelephonyManager上,与AOSP升级冲突风险极高
-
参考: Android 16 的 SatelliteManager 独立入口
-
建议: 创建 XwSatelliteManager 适配层,内部委托给TelephonyManager XW方法
-
收益: 为未来AOSP升级提供迁移路径,降低代码冲突
-
实施:
-
public class XwSatelliteManager { public static final String SATELLITE_SERVICE = "xwos_satellite"; public void requestSatelliteEnabled(boolean enabled, Executor exec, OutcomeReceiver<Void, SatelliteException> callback); public void sendDatagram(int datagramType, byte[] data, Executor exec, OutcomeReceiver<Void, SatelliteException> callback); public void registerSatelliteStateChangeListener(Executor exec, SatelliteStateChangeListener listener); public boolean isSupported(); // 内部委托: tm.setRadioPowerXw(), tm.dialXw(), tm.registerCallStateListener() }
-
3. 实现 Datagram 消息队列与重试机制
-
问题: 无消息队列,语音/数据直接透传HAL,无重试、无超时、无紧急优先
-
参考: Android 16 的 DatagramDispatcher(LinkedHashMap队列 + retrySendingDatagrams() + SATELLITE_RESULT_MODEM_TIMEOUT)
-
建议: 新建 XwDatagramDispatcher 类,实现消息队列、重试、超时、紧急/普通分离
-
收益: 消息投递可靠性大幅提升
-
实施:
-
public class XwDatagramDispatcher extends Handler { private LinkedHashMap<Long, SendDatagramArgument> mPendingEmergencyDatagrams; private LinkedHashMap<Long, SendDatagramArgument> mPendingNonEmergencyDatagrams; private static final int SEND_TIMEOUT_MS = 30000; void sendDatagram(SendDatagramArgument arg) { if (arg.isEmergency) mPendingEmergencyDatagrams.put(arg.id, arg); else mPendingNonEmergencyDatagrams.put(arg.id, arg); sendMessage(obtainMessage(CMD_SEND_DATAGRAM, arg)); } void retrySendingDatagrams() { for (SendDatagramArgument arg : mPendingEmergencyDatagrams.values()) { sendMessage(obtainMessage(CMD_SEND_DATAGRAM, arg)); } for (SendDatagramArgument arg : mPendingNonEmergencyDatagrams.values()) { sendMessage(obtainMessage(CMD_SEND_DATAGRAM, arg)); } } }
-
4. HAL 接口标准化
-
问题: IXwRadio/IXwRadioVoice 完全私有,无法适配其他卫星星座
-
参考: Android 16 的 ISatellite 标准HAL + SatelliteImplBase 抽象基类
-
建议: 在 IXwRadio 之上增加 ISatelliteHardware 抽象层,实现类似 SatelliteImplBase 的厂商抽象基类
-
收益: 支持多星座适配,与AOSP HAL演进对齐
5. 补充紧急SOS功能
-
问题: 无独立SOS接口,dialXw未区分普通/紧急呼叫
-
参考: Android 16 的 DATAGRAM_TYPE_SOS_MESSAGE + SatelliteSOSMessageRecommender + T911/SOS双模式 + ESOS Profile
-
建议: 增加 emergencyDialXw() 和 sendSosDatagram(),实现紧急呼叫推荐机制
-
收益: 满足3GPP紧急呼叫要求,与AOSP卫星SOS对齐
6. 增加卫星流量统计支持
-
问题: 完全缺失卫星流量统计能力,卫星流量混入移动网络流量,用户/应用无法精确计量卫星数据消耗,无计费属性区分
-
参考: Android 16 的 NetworkTemplate.Builder.setTransportType(TRANSPORT_SATELLITE) + NetworkIdentity.mTransportTypesBits + NetworkStatsService 卫星识别机制
-
建议: 分层实现卫星流量统计支持:
- 方案A(框架层修改,推荐) :参考 Android 16 机制,在 NetworkIdentity 中增加 TRANSPORT_SATELLITE 位支持,在 NetworkTemplate.Builder 中增加 setTransportType(),在 NetworkStatsService 中增加卫星接口识别逻辑(isMobile 判断包含 TRANSPORT_SATELLITE),实现 XwNetworkStatsManager 提供卫星专用流量查询接口
- 方案B(应用层补偿) :若无法修改框架层,可在 TeleDataService 中自行记录卫星接口的 RX/TX 字节数,通过 TrafficStats.getUidRxBytes()/getUidTxBytes() 结合接口名称过滤,实现应用级卫星流量统计
- 方案C(混合方案) :启用 Android 16 的 FLAG_NETSTATS_TRANSPORT_TYPE Feature Flag(如已回移),配合自定义 NetworkTemplate 构建卫星查询模板
-
收益: 用户可精确计量卫星数据消耗,支持计费感知,为运营商计费对接提供基础
-
OEM适配要点:
- 内核/HAL层:确保卫星网络接口被正确注册到TelephonyNetworkSpecifier中,包含正确的subscriptionId;卫星Modem需通过PhoneStateListener上报RAT类型;eBPF程序无需修改,卫星流量通过标准网络接口采集
- Framework层:启用FLAG_NETSTATS_TRANSPORT_TYPE Feature Flag以支持基于传输类型的模板查询;在getDisplayTransport()实现中正确映射卫星传输类型;确保卫星网络的NetworkCapabilities包含TRANSPORT_SATELLITE
- 流量统计区分:如需独立统计卫星流量,使用NetworkTemplate.Builder().setTransportType(TRANSPORT_SATELLITE).build()构建查询模板;注意此功能受Feature Flag控制,需确认设备已启用
-
实施(方案A) :
-
// 1. NetworkIdentity 增加 TRANSPORT_SATELLITE 位 public class NetworkIdentity { // 在 Builder.setTransportTypes() 中处理 TRANSPORT_SATELLITE } // 2. NetworkTemplate.Builder 增加 setTransportType public static class Builder { public Builder setTransportType(@Transport int transportType) { mTransportType = transportType; return this; } } // 3. NetworkStatsService 增加卫星识别 // handleNetworkStateChanged() 中: final boolean isMobile = NetworkCapabilities.TRANSPORT_CELLULAR == displayTransport || NetworkCapabilities.TRANSPORT_SATELLITE == displayTransport; // 4. XwNetworkStatsManager 提供便捷查询 public class XwNetworkStatsManager { public NetworkStats.Bucket getSatelliteUsage(long start, long end) { NetworkTemplate template = new NetworkTemplate.Builder() .setTransportType(NetworkCapabilities.TRANSPORT_SATELLITE) .build(); return mNsManager.querySummaryForDevice(template, start, end); } }
-
中优先级
7. 实现信号上报体系
-
问题: 无信号变化事件上报,仅通过customRequest主动查询
-
参考: Android 16 双路径信号上报(OEM卫星模式 + 运营商NTN漫游模式)+ 5级离散模型 + 滞后滤波
-
建议: 在 IXwRadioIndication 中增加 onSignalStrengthChanged() 回调,实现5级离散信号模型+滞后滤波,支持 INtnSignalStrengthCallback 注册机制
-
收益: 支持信号质量实时监控和UI展示
8. 实现地面/卫星自动切换
-
问题: 无自动切换机制
-
参考: Android 16 的 onTerrestrialNetworkAvailableChanged() + CarrierConfig自动切换 + 并发地面扫描
-
建议: 在 TeleDataService 中增加地面网络恢复检测,根据配置自动切换
-
收益: 用户体验提升,功耗优化
9. 类型安全增强
-
问题: CallState 的 dir/stat/mode/rate 均为裸int
-
建议: 添加 @IntDef 注解定义合法值集合
-
收益: 编译期类型检查,防止非法值
10. 统一异步回调模式
-
问题: 混用 Consumer/ResultReceiver/IIntegerConsumer/OutcomeReceiver
-
参考: Android 16 统一使用 OutcomeReceiver
-
建议: 统一为 OutcomeReceiver 模式,废弃 IIntegerConsumer/IBooleanConsumer
-
收益: API一致性
11. 可观测性增强
-
问题: 缺少消息发送时延统计、链路质量指标
-
参考: Android 16 的7个Metrics类 + PersistentLogger
-
建议: 在 TeleStatsService 中增加卫星消息时延、链路建立时延、错误率等指标;实现关键事件持久化
-
收益: 支持运维监控和用户体验优化
12. CarrierConfig 集成
-
问题: 无运行时配置机制
-
参考: Android 16 的 CarrierConfigManager 按PLMN配置卫星策略
-
建议: 通过 CarrierConfigManager 按PLMN配置超时、优先级、ESOS Profile、并发地面扫描等
-
收益: 支持多运营商差异化配置
13. 动态配置管理
-
问题: 编译时固定常量,无法OTA更新
-
参考: Android 16 的 SatelliteConfigParser(protobuf) + SatelliteNetworkInfo
-
建议: 实现 SatelliteConfigParser 类似功能,支持protobuf格式的OTA配置更新
-
收益: 支持运行时配置更新,无需刷机
低优先级
14. 实现对星引导UI
-
问题: 无对星引导
-
参考: Android 16 的 PointingAppController + needFullScreenPointingUI 参数 + AntennaPosition
-
建议: 增加 XwPointingController,在拨号/发送前引导用户对准卫星
15. 权限模型完善
-
问题: 无独立卫星权限
-
参考: Android 16 的 USE_SATELLITE 权限 + 系统弹窗
-
建议: 定义 android.permission.USE_XW_SATELLITE 权限
16. Binder生命周期统一管理
-
问题: registerCallStateListener 有 linkToDeath,registerForCustomEventListener 没有
-
建议: 统一所有监听器注册的死亡通知处理;将 sCustomEventListeners 从 HashMap 改为 ConcurrentHashMap
17. 修复已知Bug
-
问题: setPostimeXwAsync 的catch日志复制粘贴错误
-
建议: 修正日志标签
18. 测试框架搭建
-
问题: 无任何测试代码
-
参考: Android 16 的 DemoSimulator + CTS + @VisibleForTesting
-
建议: 为核心类编写单元测试,实现DemoMode测试模式
19. 位置服务功耗优化
-
问题: 固定轮询策略(100s/1500m),GPS持续开启
-
参考: Android 16 的 startSatellitePositionUpdates 按需模式
-
建议: 引入自适应策略——CP入网后降低频率,运动检测触发上报
20. XwTelephonyManager 与 TelephonyManager 去重
-
问题: 功能重复
-
建议: 明确 XwTelephonyManager 定位为适配层,内部仅委托调用
21. 保留Kylin独有功能
-
问题: 标准化后可能丢失差异化竞争力
-
参考: Android 16 的 SatelliteImplBase 厂商扩展机制
-
建议: 在标准化框架基础上,通过Vendor扩展命名空间保留语音通话、安全卡、摇晕摇毙、载波模式、CP电源管理等定制功能
八、总结与参考建议
核心差异总结
| 维度 | Android 16 AOSP | Kylin Android 13 | 评价 |
|---|---|---|---|
| 定位 | 全球通用卫星基础设施 | 星网专用全业务方案 | 互补而非替代 |
| 架构成熟度 | ⭐⭐⭐⭐⭐ 模块化、9态状态机、消息队列、指数退避 | ⭐⭐⭐ 功能完整但架构封闭、无状态机 | AOSP架构更优 |
| 功能完整度 | ⭐⭐⭐ 仅消息/SOS/数据/信号/配置 | ⭐⭐⭐⭐⭐ 语音+数据+位置+统计+安全+自定义 | Kylin功能更全 |
| 可靠性 | ⭐⭐⭐⭐⭐ 队列+重试+超时+状态守卫+指数退避 | ⭐⭐ 无队列无重试无超时 | AOSP远优于Kylin |
| 可升级性 | ⭐⭐⭐⭐⭐ Mainline APEX + 零侵入 | ⭐⭐ 侵入frameworks + 私有HAL | AOSP远优于Kylin |
| 多星座支持 | ⭐⭐⭐⭐ 标准HAL抽象 + NTRadioTechnology枚举 | ⭐ 仅星网(高轨/低轨) | AOSP远优于Kylin |
| 功耗管理 | ⭐⭐⭐⭐⭐ 灭屏超时+分级会话+干扰源+并发扫描 | ⭐⭐ 无功耗管理 | AOSP远优于Kylin |
| 可观测性 | ⭐⭐⭐⭐⭐ 7个Metrics类+PersistentLogger | ⭐⭐⭐ TeleStatsService(仅通话) | AOSP更全面 |
| 代码质量 | ⭐⭐⭐⭐⭐ 类型安全+线程安全+完整Javadoc+测试 | ⭐⭐⭐ 部分类型不安全+线程风格不一致+无测试 | AOSP远优于Kylin |
| 卫星流量统计 | ⭐⭐⭐ 基础识别架构(TRANSPORT_SATELLITE位+模板查询+合并统计),无独立API/专属策略 | ⭐ 完全缺失,卫星流量混入移动流量 | AOSP有基础但尚不完整;Kylin完全缺失 |
长期演进建议
-
短期(3-6个月) : 实施高优先级优化——状态机实现、SatelliteManager适配层、Datagram消息队列、HAL标准化、SOS功能、卫星流量统计支持
-
中期(6-12个月) : 实施中优先级优化——信号上报、自动切换、类型安全、回调统一、可观测性、CarrierConfig、动态配置
-
长期(12+个月) : 规划AOSP升级路径——当升级到Android 14+时,逐步将XWOS功能迁移到AOSP SatelliteManager框架,保留星网特有功能(语音通话、CP电源管理、安全卡、载波模式)作为Vendor扩展接口;同步推进流量统计能力标准化,确保卫星流量可独立查询、可计费关联、可按波束/运营商细分。具体方向包括:(1) 推动AOSP实现独立的卫星流量统计API(如getSatelliteUidStats());(2) 在NetworkStats.Entry中增加TYPE_SATELLITE网络类型常量;(3) 实现SatelliteAccessController与NetworkStatsService的集成,在卫星网络启用/禁用时触发流量统计标记;(4) 支持按波束/运营商的卫星流量细分统计;(5) 为卫星消息模块(DatagramController/DatagramDispatcher)增加流量统计调用
风险提示
- AOSP升级冲突: 当前侵入式修改 TelephonyManager 和 ITelephony.aidl 的方式,在升级到 Android 14+ 时将产生严重合并冲突。越早解耦,升级成本越低。
- 状态机缺失风险: 无状态守卫可能导致CP在OPENNING状态收到dialXw请求,造成不可预期的行为。
- 消息丢失风险: 无队列无重试机制,在网络不稳定时消息可能丢失且无法恢复。
- 3GPP NTN标准化: 随着NTN标准成熟(Release 18/19),AOSP卫星框架将逐步支持语音和数据业务,Kylin的私有实现可能需要重写。
- customRequest迁移: 107个Custom Request ID需逐一映射到标准AIDL方法或Vendor扩展接口,工作量较大。
- XwosTeleService进程管理: 独立进程增加系统复杂度(进程间通信、生命周期管理、崩溃恢复),需评估是否可合并到Phone进程。
- CONNECED拼写错误: XwRadioState.CONNECED 应为 CONNECTED,此拼写错误已扩散到所有使用处,修正时需全局替换。
- 卫星流量统计缺失风险: 卫星通信按流量计费是典型场景,当前无法精确计量卫星数据消耗,可能导致用户产生意外高额费用,影响用户体验和运营商合作。