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

目录

​​​背景

怎么定位的

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

第二步:抓崩溃日志

第三步:确认崩溃链路

第四步:尝试修复

怎么修改的

总结


背景

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

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

怎么定位的

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

抓取 dmesglogcat,发现蓝牙 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 这一行就已经指明了根因,剩下的只是顺着它往下查。

相关推荐
hai_android2 小时前
Kotlin Flow combine 源码剖析:一个 Channel 如何优雅合并多条流
android·java·kotlin
敲代码的瓦龙3 小时前
Jetpack?ViewModel!!!
android·开发语言·kotlin·android-studio
Godikov4 小时前
Android 工控终端实战:从秒级卡顿到毫秒响应,SQLite/LitePal 性能优化全记录
android
星间都市山脉5 小时前
Android16 SystemService.onBootPhase 调用时机
android·java·linux·windows·ubuntu
swithun5 小时前
不用 WebView,我用 Kotlin + Compose Multiplatform 重写 Mermaid,并做了 2048 组对拍
android·开源·kotlin
AI吃大瓜6 小时前
人脸检测和行人检测4:Android实现YOLOv8 YOLO11 YOLO26人脸检测和人体检测(含源码,可实时检测)
android·yolo·人脸检测·人体检测·行人检测·yolo26
与海boy6 小时前
Prompt模版
android·prompt
FlightYe6 小时前
音视频修炼之编码器(一):AVC、HEVC编码器内部
android·linux·c++·音视频
智购科技无人售货机工厂6 小时前
2026自动售货机AI智能体架构:从47个小模型到33.7亿Token的工程实践~YH
android·人工智能·驱动开发·单片机·pandas