十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Nexus 5 Ubuntu Touch通话并发之谜:从RIL到oFono的排查指南

Nexus 5 Ubuntu Touch通话并发之谜:从RIL到oFono的排查指南 如果你手里正好有一台闲置的 Nexus 5并且你曾经尝试把它刷成 Ubuntu Touch那大概率会遇到这样一个场景系统安装完成通话功能看起来正常但在第一个通话还保持连接时第二个电话拨进来屏幕上没有出现“新来电”的提示甚至第一个通话可能被直接挂断。你会很自然地冒出一个疑问这个能装进一部实体手机的 Linux 系统为什么连“同时接听来电去电”这种最基础的电话能力都处理不好其实这不是一个简单的 UI 缺失问题。它背后涉及基带、RIL 驱动、系统服务、通话状态机和运营商网络配置的整个链条。这篇文章想把这个链条讲清楚并提供一个可执行的验证和排查路线。我先把结论放在前面在 Nexus 5 Ubuntu Touch 这个组合上是否能在通话中来电并保持原通话、再主动拨出第二路取决于你刷入的版本、基带固件、RIL 与 oFono 对该调制解调器补充业务能力的支持情况而不是光在设置里找一个开关就能解决。1. 先分清你玩的 Ubuntu Touch不是“能在手机上跑的 Ubuntu 桌面”1.1 桌面 Ubuntu 经验在这里只能帮你识别文件系统很多人对 Ubuntu 的第一印象来自虚拟机、双系统安装、镜像文件刻录或者是在一台 PC 上折腾输入法、Docker 和显卡驱动。这些经验能让你快速理解 APT 包管理、systemd 服务、日志系统和用户权限但在 Nexus 5 上的 Ubuntu Touch 并不是把桌面 Ubuntu 塞进手机那么简单。Ubuntu Touch 是一套面向移动设备的系统它的 UI 层、应用生命周期、后台任务策略、触控输入处理都完全不同于桌面版。更关键的是手机系统要管理一个桌面电脑通常没有的东西调制解调器。打电话不是 App 自己发一条指令就能完成的基带固件和 AP应用处理器之间必须有一套稳定的协作机制。所以把桌面版 Ubuntu 和 Ubuntu Touch 区别开来是理解本文主题的第一步。如果沿用桌面 Linux 的思路你会很容易认为“通话功能只是某个 App 的事情”但实际上它属于一个完整的设备子系统。桌面经验能帮你理解日志、服务、权限和包管理但不能帮你跳过电话栈的部分。1.2 Ubuntu Touch 的通信侧采用分层架构在常见实现里Ubuntu Touch 的通话链路可以简化成基带 - RIL 驱动 - oFono电话抽象服务 - 电话应用/UI。RIL 负责把上层意图翻译成调制解调器能理解的命令oFono 是面向嵌入式设备和服务器的电话栈由上层应用通过 D-Bus 查询和操作通话对象。这意味着一次拨号动作至少会经过 UI 服务、oFono、RIL、设备节点、基带固件再到运营商网络。每一层都有可能出现“能力缺失”。比如 GUI 支持显示呼叫等待但 oFono 的某个状态对象没有处理 waiting或者 RIL 驱动在某个固件版本里不支持保持通话相关命令那么“保持通话/拨打第二路”就无从实现。这也是为什么同一个功能在 Android 上正常、在 Ubuntu Touch 上异常并不奇怪。两边上层应用依赖的底层电话栈完全不同Android 对通话并发的处理已经成熟而 Ubuntu Touch 的移动电话支持长期只覆盖了最核心的基础通话。1.3 Nexus 5 是这个实验的经典入口Nexus 5 在 Ubuntu Touch 早期是官方支持的设备之一社区资料较多救砖流程也相对成熟。相比其他冷门设备你更容易找到对应型号的 system image、recovery 和讨论帖。不过要注意官方支持不等于所有功能都有同等完成度。刷入某个版本后可能 Wi-Fi 正常、GPS 正常但语音通话或数据切换有已知问题。所以准备一个实验前最好先确认你要测的版本在 Nexus 5 上的已知问题列表而不是默认“能开机就等于能打电话”。2. 同一部 Nexus 5 上实现“来电去电”并存先确认边界2.1 硬件和网络环境决定第一道红线Nexus 5 是单卡设备机身上没有两个 SIM 槽。这里的“同时接听来电去电”不是指双卡双待那种两个物理号码同时在线而是指在同一张 SIM 卡、同一条移动网络链路上同时维护两个通话会话。在 GSM/WCDMA/LTE 网络下这需要几个前置条件同时成立运营商网络提供呼叫等待、呼叫保持、多方通话等补充业务你的号码已经开通了这些业务基带和调制解调器固件能够处理多呼叫的状态RIL/oFono 把多个呼叫对象正确暴露给上层。这四条里任何一条不满足都会表现成“第二个电话打不进来”或“一通话就把第一个通话挤断”。有很多人刷完系统后第一反应是“这个系统连呼叫等待都没做”但实际上问题出在运营商没开通业务或者系统里的电话栈版本太旧。2.2 “同时”的本质是呼叫保持不是一个物理通道从通信协议角度看单卡手机的“通话中接听另一个来电”其实是把一个通话挂起再把音频通道切换给另一个通话。两个呼叫并没有真正同时占用两条独立的音频链路而是由系统在它们之间切换。这个机制在移动网络里对应的是呼叫保持与呼叫等待等补充业务。一个正常支持语音的 Android 手机默认会处理这套流程因为 Android 的 Telephony 框架已经把它做成了“等待接通/保持通话/切换通话”的操作。而 Ubuntu Touch 的定制电话栈不一定把这条路完整实现。所以在测试前先别混淆如果你的目标是“在第一个电话保持期间接听第二个电话再回到第一个电话”那么你要找的并不是“同时接听”这个字眼而是系统是否实现了“Wait/Hold/Swap”这组状态。如果只实现了前面两个状态但没有实现切换你仍然会卡在“两个通话都建立了却切不回去”的尴尬局面。2.3 版本差异可能让同一个设备表现完全不一样Ubuntu Touch 并不是一个一劳永逸的单一版本。从早期的 Ubuntu for Phones 到后来的社区维护版本期间有很多变化。不同版本对电话栈的依赖可能不同有的版本甚至有专门的 cellular 相关修订。如果你想验证“来电去电并存”最稳妥的做法是找一个设备支持页上明确列出通话功能相对稳定的版本先在该版本上做完整回归再考虑升级。升级后必须重新测试因为底层的 oFono 或 RIL 驱动一旦变化就会直接影响这个功能。注意不要一上来就测复杂流程先确认基础语音通话、挂断、接听都没有问题再进入通话并发测试。基础链路不稳固时并发测试的结果没有参考价值。3. 一条通话背后的完整链路从基带到屏幕上的通话界面3.1 AP 与基带各管一摊不是 App 直接操作硬件现代智能手机里有两个主要处理器AP应用处理器运行操作系统和 App基带处理器负责与基站通信、语音编解码、信号处理等。二者通常通过共享内存、串口、USB 或 PCIe 等通道通信。这意味着“拨号”这个动作由 AP 上的电话应用发起但真正把呼叫建立起来的是基带。AP 只能通过 RIL 向基带发送指令然后从基带得到事件回调。如果基带报告了“第二个呼叫进入”但 AP 侧没有把它渲染成 UI 事件用户就看不到任何来电提示如果 AP 侧没有向基带发出保持/接听指令第二个呼叫就只能按预定义策略被自动拒绝或直接进入忙音。这个分工的影响非常大。很多人在调试时习惯盯着 GUI 看但当一个电话功能不正常时它可能从未到达 GUI也可能早就到达了 GUI 但 GUI 没有正确渲染。你必须先判断事件到底在哪一层丢失。3.2 RIL 与 oFono系统里的翻译层RIL 的全称是 Radio Interface Layer它将上层请求翻译成基带指令并把基带事件翻译成上层能理解的格式。Android 系统自带一套成熟的 RIL 框架Ubuntu Touch 则通过 oFono 或类似电话抽象层来管理调制解调器。在常见 Ubuntu Touch 架构里oFono 扮演了调制解调器管理者和呼叫状态机的角色。上层电话应用通过 D-Bus 调用 oFono 的接口比如查询 Modem 状态、创建出呼、监听来电事件等。如果 oFono 在代码层面没有把多个呼叫对象暴露出来那么即使基带和网络都支持呼叫保持上层也没有入口去操作它。这也是为什么很多人尝试用命令直接操作 D-Bus、查看呼叫对象而不是只盯着图形界面。查看这些接口可以判断一个问题到底出在底层还是出在 UI。3.3 通话状态机第二个电话为什么可能被“吃掉”一次普通通话有多种状态。常见状态包括idle空闲dialing出呼拨号中incoming来呼振铃中active通话连接中held被保持waiting已有通话时的第二通来电如果电话栈实现了 waiting 和 held当第一个通话是 active 时第二个 incoming 可以被标记为 waiting用户可以选择应答、拒绝或保持现状。如果这里缺少对 waiting 的处理系统可能直接将第二个呼叫拆线或转成未接。这个状态机通常定义在 oFono 或上层的呼叫管理者里。你可以通过查看 D-Bus 对象树来观察系统把一个呼叫放进了哪个状态。这个信息对排查很有用。dbus-send --print-reply --destorg.ofono /ril_0 org.ofono.Modem.GetProperties上面是常见调用的示例具体对象路径和接口名会随版本略有差异但思路一致先看到调制解调器对象再通过它找到呼叫列表和状态。如果这个工具在你的版本里不存在也可以查一下ofonoctl或者直接翻系统日志。4. 从单通话到“来电去电并存”的验证路径4.1 准备一个最小环境一台刷好 Ubuntu Touch 的 Nexus 5一张开通了呼叫等待业务并至少有一个语音套餐的 SIM 卡以及至少两个其他号码用于打电话给你。测试前先确认系统的基础通话功能正常能正常接听能正常挂断网络信号稳定没有处于飞行模式或省电模式进入设置查看 SIM 是否有被误设置为“只允许数据”不要用 Nexus 5 给自己另一个号打电话来测试因为运营商逻辑会干扰判断最好用两个不同的外部号码。不要跳过这一步。很多问题在后来的复杂测试里暴露但根源是最基础的网络注册没完成。4.2 做第一次主叫测试用另一个号码号码 A拨打 Nexus 5 的号码等 Nexus 5 接听确认音频通路正常。挂断后再用 Nexus 5 主动呼叫号码 A确认出呼正常。这一步完成说明基带、RIL、oFono、音频通路都通畅。如果在这一步就出现“接通后没声音”“拨出后立即断线”等问题不要继续测并发先把基础通话修好。否则后面所有结果都无法定位。4.3 验证“第二通来电”的表现保持 Nexus 5 与号码 A 通话让号码 B 拨打同一个 SIM 卡号码观察屏幕有没有出现第二个来电请求有没有“接听并提供保持”或“挂断当前并接听”的选项第一个通话是否仍处于活动状态如果选了接听第一个通话是保持、挂断还是没有变化能不能在两个通话之间切换。记录下每个步骤的实际表现不要凭印象。这个功能在不同固件、不同版本下表现可能完全不同。如果系统没有提供任何新来电提示先不要急着给结论看日志再判断。可以通过 adb 进入设备 shell然后查看电话栈进程日志adb shell ps aux | grep -i ofono journalctl -u ofono -f如果你的版本没有 systemd 或没有名为 ofono 的 unit可以换成查看 oFono 进程对应的输出或者查看~/.cache/upstart下的日志。重点是找到电话栈在收到“新来电事件”后做了什么。4.4 如果第二条通话没出现从哪里查起推荐这个排查顺序先查网络呼叫等待业务有没有开通运营商是否支持再查固件当前基带版本和 RIL 驱动是否匹配再查服务oFono 是否识别到调制解调器并把 Modem 状态置为 online再查状态第二个来电到来时oFono 是否创建了新的呼叫对象状态有没有进入 waiting最后查 UI如果底层已经出现 waiting 状态但界面上没有按钮那是 UI 层没有渲染对应状态。如果底层根本没生成 waiting 对象那问题不在 UI而在 RIL/oFono 对“多呼叫”的支持。这种情况下调试 GUI 没有意义。如果日志显示系统根本没有处理 waiting 状态优先检查电话栈版本是否支持多通话会话不要盲目修改参数配置。有些能力缺失是版本层面的不是开关层面的。5. 实际操作中避不开的坑5.1 固件版本和 modem 驱动不匹配表现比功能缺失更隐蔽Nexus 5 有多个 Android 基带版本Ubuntu Touch 的 RIL 驱动通常针对特定 modem 版本验证。如果你之前在 Android 上做过降级或刷入过第三方固件基带的 NV 数据和版本可能和 Ubuntu Touch 的预期不一致。这会导致通话注册正常但补充业务不响应甚至随机重启。所以这类实验最好从一个干净的设备状态开始。如果可以先通过官方工具恢复到 Android 4.4 或较稳定的版本再完整刷入 Ubuntu Touch而不是在残留的 Android 基带配置上叠加新系统。很多人遇到“刷完 Ubuntu Touch 死活无法呼叫等待”的问题最后发现是残留固件里的 modem 配置和当前系统不匹配。5.2 单次能接通不等于并发可用很多人测得“能打电话”后就认为电话栈是完好的。但实际上单通话可用、双通话不可用在软件工程里非常普遍。因为两个状态路径对应的是不同的代码分支RIL 驱动不一定把通话保持相关命令完整翻译给基带。你可以在测试列表里把“单通话”和“多通话”分成两个用例单独记录。不要因为一个用例通过就推断另一个也会通过。这个习惯不仅适用于手机系统也适用于其他异步流程的调试。5.3 排查时先分层别在 GUI 上浪费时间一个很容易犯的错误是屏幕没有显示新来电就开始怀疑电话应用。更合理的做法是先确认底层有没有来电事件再确认有没有生成呼叫对象然后逐层向上。排查层常见节点典型问题网络层SIM 注册、补充业务、信号运营商未开通呼叫等待固件层基带版本、NV 配置基带与 RIL 驱动版本不匹配驱动层设备节点、RIL 进程调制解调器未被正确识别系统服务层oFono、呼叫状态机未生成 waiting/held 对象应用层电话 UI、通知状态对象存在但未渲染这张表也适用于其他 Linux 手机实验。出现问题先看层不要从最外层开始猜。很多社区求助帖最后定位到的问题都出在“网络层未开通业务”或“固件层版本不匹配”而不是系统本身不支持。5.4 如果你想长期日用还差这几块拼图即便你把通话并发调通了Ubuntu Touch 作为日常手机仍然要面对几件现实事VoLTE 支持有限、部分银行类和聊天类 App 无法使用、连接车机或蓝牙耳机时可能出现音频问题、系统更新节奏不固定。这意味着它更适合作为“实验设备”或“备用机”而不是主力机。它的价值在于让你理解手机系统的分层结构而不是替代 Android 或 iOS 的完整成熟度。如果你接受这一点那它带来的认知收益会比一台流畅的主力机更大如果你不接受它会很快变成抽屉里的电子垃圾。6. 给想要尝试的人一个可复用的判断框架6.1 六个问题判断一个方案能否进入日常当你又看到某个“Linux 手机完全可用”的说法时试着用下面六个问题过滤一下问题想清楚什么电话基础能力是否完整能稳定收短信、打电话、保持通话吗补充业务是否支持呼叫等待、呼叫保持、多方通话常用 App 是否覆盖支付、聊天、扫码、地图续航和散热是否可用是否低电关机、异常发热升级是否会破坏功能每次 OTA 后是否需要重新调试出现问题是否可诊断有日志、社区、文档能帮你定位如果六个问题里有三个以上是“不确定”或“不行”这个方案更适合作为实验。如果都不想放弃那就必须接受它的边界。技术项目的“能运行”和“能日常使用”之间隔着的正是这些看起来琐碎但每天都会遇到的小问题。6.2 这个实验真正值得做的原因Nexus 5 Ubuntu Touch 的“同时接听来电去电”在今天已经不是一个主流需求。你不太可能为了这个功能特意刷机。但它仍然值得做原因是它能让你看见手机系统里那些平时被完全隐藏起来的层次。Android 的成熟让大多数用户不需要理解 RIL、oFono、基带和状态机。而一个实验性的系统会让你被迫面对这些概念因为你需要从头判断问题出在哪一层。这种排查训练比单纯安装一个工具更能提升你对设备体系的理解。同时这也是一个很好的“预期管理”样本。技术项目能够运行和能够进入日常使用是完全不同的两个阶段。在桌面 Linux 上安装个软件很容易但在一个移动设备上把整条通信链路全部打通需要的时间比想象中多得多。回到最初的问题Nexus 5 上用 Ubuntu Touch 能不能同时处理来电和去电答案是“取决于版本和网络条件建议实测而不是看 GUI”。如果你只是做实验把它当作一个电话栈功能的试金石如果你是想换主力机我建议先用一个低成本的号码在这台设备上完整使用一周再决定是否继续。
返回列表