记一次 RK3568 Android 13 蓝牙反复重启问题的排查与修复

目录

​​​背景

怎么定位的

第一步:确认底层是否正常

第二步:抓崩溃日志

第三步:确认崩溃链路

第四步:尝试修复

怎么修改的

总结


背景

项目基于 RK3568 + Android 13 进行系统裁剪,目标是去除不必要的系统应用以减小镜像体积。在移除联系人应用后,发现蓝牙功能异常:能扫描到设备,但无法稳定开启,日志中大量出现 [BT_RFKILL]: bt shut off power 与 bt turn on power 的循环。

一开始怀疑是固件缺失、HAL 库被删或驱动问题,但检查后发现 rtl8822cs_fw、rtl8822cs_config、libbt-vendor-realtek.so、android.hardware.bluetooth@1.0-impl.so 等文件全部存在,SELinux 策略、UART 权限也正常。问题显然不在底层。

怎么定位的

第一步:确认底层是否正常

抓取 dmesg 和 logcat,发现蓝牙 HAL 其实已经成功初始化:

  • 固件下载成功:vendor lib fwcfg completed

  • HCI 初始化成功:android.hardware.bluetooth@1.0-impl: OnFirmwareConfigured result: 0

说明蓝牙芯片、固件、HAL 都是好的。问题在上层。

第二步:抓崩溃日志

用以下命令过滤 AndroidRuntime 崩溃:

bash 复制代码
logcat -b all -s AndroidRuntime:E | grep -i "BluetoothPbapService"

日志中反复出现同一个异常:

bash 复制代码
java.lang.RuntimeException: Unable to start service com.android.bluetooth.pbap.BluetoothPbapService ...
java.lang.SecurityException: Failed to find provider com.android.contacts for user 0; 
expected to find a valid ContentProvider for this authority

根因清晰了 :BluetoothPbapService 启动时需要访问 com.android.contacts 的 ContentProvider,但联系人应用被裁剪掉了,Provider 不存在,服务启动失败,抛出的 SecurityException 直接导致整个蓝牙进程崩溃。

第三步:确认崩溃链路

继续抓 BluetoothManagerService 的日志:

bash 复制代码
logcat -b all -s BluetoothManagerService:D

可以看到完整的崩溃链路:

  1. 蓝牙服务启动 → MESSAGE_BLUETOOTH_SERVICE_CONNECTED

  2. PBAP 服务启动失败,进程崩溃 → MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED

  3. 系统尝试重启蓝牙服务 → MESSAGE_RESTART_BLUETOOTH_SERVICE: retry count=1

  4. 再次崩溃,循环往复

这就是蓝牙状态反复跳变的根本原因。

第四步:尝试修复

第一次尝试(失败) :设置 persist.bluetooth.pbap.server.enabled=false。

结果重启后无效。用 getprop | grep -i pbap 检查发现:

bash 复制代码
[bluetooth.profile.pbap.server.enabled]: [true]   ← 真正生效的属性
[persist.bluetooth.pbap.server.enabled]: [false]  ← 无效属性

原来 Android 13 蓝牙栈读取的是 bluetooth.profile.pbap.server.enabled,而不是带 persist. 前缀的那个。

第二次尝试(成功):设置正确的属性:

bash 复制代码
setprop bluetooth.profile.pbap.server.enabled false

重启蓝牙后,日志中不再出现 BluetoothPbapService 崩溃,蓝牙状态稳定停留在 ON,问题解决。

怎么修改的

setprop 只在当前运行有效,因为 bluetooth.profile.pbap.server.enabled 不带 persist. 前缀,重启后会恢复默认值 true。要永久生效,必须固化到 SDK 源码。

在设备的 init.rc(如 device/rockchip/rk356x/init.rk356x.rc)中添加:

bash 复制代码
on boot
    setprop bluetooth.profile.pbap.server.enabled false

on boot 触发时,所有 build.prop 都已加载完毕,此时 setprop 的值不会再被覆盖,蓝牙服务后续读取到的就是 false。

总结

这次问题的本质是系统裁剪时移除了联系人应用,但没有同步关闭依赖它的蓝牙 PBAP Profile,导致上层 Java 服务启动失败并拖垮整个蓝牙进程。

几个关键经验:

  1. 裁剪系统应用时要检查依赖链。删除一个应用可能影响其他模块,尤其是蓝牙、通话、短信这类有 Profile 依赖的系统服务。

  2. Android 属性前缀很重要 。persist. 前缀的属性才会持久化,不带前缀的只影响当前运行。设置属性前先用 getprop | grep 确认属性名是否正确。

  3. 定位问题要分层 。先从 dmesg 确认底层(驱动、固件、HAL),再看 logcat 上层(Java 服务、系统进程),避免在错误的方向浪费时间。

  4. setprop 只适合临时验证,固化配置要改源码 。找到正确的属性名后,最终方案是写进设备的 init.rc中,保证每次开机默认值正确。

  5. 崩溃日志里的异常栈是最直接的线索 。SecurityException: Failed to find provider com.android.contacts 这一行就已经指明了根因,剩下的只是顺着它往下查。

相关推荐
五彩小白8 小时前
自回归和上下文
android
事圆则缓10 小时前
Android 多渠道打包实战:Product Flavors、签名、AAB 与发包校验
android
树下困觉眯13 小时前
View绘制流程学习--获取WindowManager的三种方式
android·系统架构·view design
vilya14 小时前
我怎么给手机 GUI Agent 做双通道感知:无障碍树为主,投屏像素兜底
android·人工智能
李子红了时15 小时前
阿狸舞台APP(安卓端手机EncFS解密+压缩包解压+视频播放)
android·音视频
事圆则缓15 小时前
Android 使用 Jenkins 实现 CI/CD,并用 SonarQube 建立质量门禁
android·ci/cd·jenkins
其实防守也摸鱼15 小时前
DeepSeek Harness 开源贡献手记:从 Issue 到 Merge 的完整旅程
android·数据库·学习·ai·oracle·自动化
恋猫de小郭15 小时前
Android CLI 支持 AI Agent 通过 Device Streaming 调试云真机
android·前端·flutter
素师良码1 天前
第5篇:显示驱动必备调试工具浅析
android
维克兜率天1 天前
【维克】配对交易的季节性:哪些品种适合长拿?
android·开发语言·笔记·python·算法·kotlin·量化