Android14 待机关机蓝牙自动关闭分析解决

ops/2024/9/21 11:07:38/

Android14 待机关机蓝牙自动关闭分析解决

文章目录

  • Android14 待机关机蓝牙自动关闭分析解决
    • 一、前言
    • 二、分析解决
      • 1、分析思路
      • 2、BluetoothManagerService 关机后的主要日志
        • (1)蓝牙会关闭的日志
        • (2)蓝牙不会关闭的日志
        • (3)Google手机上蓝牙待机的日志
        • (4)分析会设置蓝牙属性值为关闭的情况
      • 3、BluetoothManagerService 去除设置蓝牙属性值为关闭的处理
    • 三、其他
      • 1、Android14 待机过程关闭蓝牙小结
      • 2、蓝牙 BluetoothService 启动和相关代码
        • (1)蓝牙服务相关的有几个类有:
        • (2)几个蓝牙类对象的关系
      • 3、Android14 Settings属性断电上电不记忆问题分析解决
      • 4、Android13 蓝牙协议属性配置详解
  • 节假日快乐,身体才是革命的本钱。

一、前言

Android14 设备蓝牙开启的情况,待机关机后再开机出现有概率蓝牙关闭的问题。

设备开机后手动打开蓝牙是可以正常打开的。

通过分析发现是上层的蓝牙服务中有监听关机广播,有关闭蓝牙动作。

但是为啥会出现有概率关闭呢,具体原因是因为有时候蓝牙关闭流程没走完或者有些蓝牙关闭流程未走到设置蓝牙关闭属性的情况。

二、分析解决

1、分析思路


(1)查看蓝牙是否记忆,因为系统中是有wifi、蓝牙属性不记忆的可能;
(2)也不排除开机后打开蓝牙异常,但是无法打开的情况。
(3)还有就是设备待机关机过程,蓝牙被设置关闭,所以待机启动后蓝牙是关闭的状态。

其实无论哪种情况,都是可以通过日志关键字 “BluetoothManagerService” 查看蓝牙过程。
BluetoothManagerService 日志里面有蓝牙开关状态,开机、关机关键过程也有相关的开关状态打印。

除了查看打印还可以通过蓝牙属性判断当前蓝牙是否是开启状态:

//获取蓝牙开关状态,0:关,1:开
adb shell settings get global bluetooth_on

查看状态主要是排除某些底层异常的情况。
有些底层异常的时候,打开蓝牙失败,
查看蓝牙是关闭的,但是蓝牙的状态数值还是打开的状态。

所以目前比较简单的思路就是:

(1)查看bluetooth_on 蓝牙的开关状态
(2)查看 BluetoothManagerService 蓝牙服务的相关日志

bluetooth_on 开关状态值的获取,我就不展示了。
主要展示下蓝牙关机后的日志:

2、BluetoothManagerService 关机后的主要日志

(1)蓝牙会关闭的日志
09-09 15:22:16.297   773   773 I BluetoothManagerService: Device is shutting down.
09-09 15:22:16.303   773   952 D BluetoothManagerService: MESSAGE_BLUETOOTH_STATE_CHANGE: ON > TURNING_OFF
09-09 15:22:16.304   773   952 D BluetoothManagerService: Sending BLE State Change: ON > TURNING_OFF
09-09 15:22:16.313   773   952 D BluetoothManagerService: Sending State Change: ON > TURNING_OFF
09-09 15:22:16.560   773   952 D BluetoothManagerService: MESSAGE_BLUETOOTH_STATE_CHANGE: TURNING_OFF > BLE_ON
09-09 15:22:16.560   773   952 D BluetoothManagerService: Intermediate off, back to LE only mode
09-09 15:22:16.560   773   952 D BluetoothManagerService: Sending BLE State Change: TURNING_OFF > BLE_ON
09-09 15:22:16.573   773   952 D BluetoothManagerService: isBleAppPresent() count: 0
09-09 15:22:16.578   773   952 D BluetoothManagerService: Sending State Change: TURNING_OFF > OFF
09-09 15:22:16.601   773   952 D BluetoothManagerService: MESSAGE_BLUETOOTH_STATE_CHANGE: BLE_ON > BLE_TURNING_OFF
09-09 15:22:16.601   773   952 D BluetoothManagerService: Sending BLE State Change: BLE_ON > BLE_TURNING_OFF
09-09 15:22:16.672   773  2893 D BluetoothManagerService: disable(): mBluetooth=android.bluetooth.IBluetooth$Stub$Proxy@d369d91, persist=true, mBinding=false
09-09 15:22:16.672   773  2893 D BluetoothManagerService: Persisting Bluetooth Setting: 0 //出现蓝牙关闭的关键日志,设置了bluetooth_on的值为0
09-09 15:22:16.700   773   952 D BluetoothManagerService: MESSAGE_DISABLE: mBluetooth =android.bluetooth.IBluetooth$Stub$Proxy@d369d91, mBinding = false
09-09 15:22:16.700   773   952 D BluetoothManagerService: Sending off request.
09-09 15:22:16.848   773   952 D BluetoothManagerService: MESSAGE_BLUETOOTH_STATE_CHANGE: BLE_TURNING_OFF > OFF
09-09 15:22:16.848   773   952 D BluetoothManagerService: Bluetooth is complete send Service Down
09-09 15:22:16.849   773   952 D BluetoothManagerService: Broadcasting onBluetoothServiceDown() to 11 receivers.
09-09 15:22:16.853   773   952 D BluetoothManagerService: unbindAndFinish(): android.bluetooth.IBluetooth$Stub$Proxy@d369d91 mBinding = false mUnbinding = false
09-09 15:22:16.878   773   952 D BluetoothManagerService: Sending BLE State Change: BLE_TURNING_OFF > OFF

从上面的日志看明细有蓝牙关闭的日志。
首先是蓝牙服务监听到系统关键的广播,然后进行了关闭蓝牙,
仔细看的话,会发现有设置蓝牙开关值的地方 “Persisting Bluetooth Setting”,
这里设置了以后,下次开机系统就会读取到蓝牙的状态为关闭从而不进行打开蓝牙。

(2)蓝牙不会关闭的日志
09-09 15:18:25.901   785   785 I BluetoothManagerService: Device is shutting down.
09-09 15:18:25.923   785   941 D BluetoothManagerService: MESSAGE_BLUETOOTH_STATE_CHANGE: ON > TURNING_OFF
09-09 15:18:25.923   785   941 D BluetoothManagerService: Sending BLE State Change: ON > TURNING_OFF
09-09 15:18:25.924   785   941 D BluetoothManagerService: Sending State Change: ON > TURNING_OFF
09-09 15:18:26.471   785   941 D BluetoothManagerService: MESSAGE_BLUETOOTH_STATE_CHANGE: TURNING_OFF > BLE_ON
09-09 15:18:26.471   785   941 D BluetoothManagerService: Intermediate off, back to LE only mode
09-09 15:18:26.471   785   941 D BluetoothManagerService: Sending BLE State Change: TURNING_OFF > BLE_ON
09-09 15:18:26.484   785   941 D BluetoothManagerService: Broadcasting onBluetoothStateChange(false) to 22 receivers.
09-09 15:18:26.485   785   941 D BluetoothManagerService: Calling sendBrEdrDownCallback callbacks
09-09 15:18:26.485   785   941 D BluetoothManagerService: isBleAppPresent() count: 0
09-09 15:18:26.516   785   941 D BluetoothManagerService: Sending State Change: TURNING_OFF > OFF
09-09 15:18:26.532   785   941 D BluetoothManagerService: MESSAGE_BLUETOOTH_STATE_CHANGE: BLE_ON > BLE_TURNING_OFF
09-09 15:18:26.532   785   941 D BluetoothManagerService: Sending BLE State Change: BLE_ON > BLE_TURNING_OFF
09-09 15:18:26.777   785   941 D BluetoothManagerService: MESSAGE_BLUETOOTH_STATE_CHANGE: BLE_TURNING_OFF > OFF
09-09 15:18:26.778   785   941 D BluetoothManagerService: Bluetooth is complete send Service Down
09-09 15:18:26.778   785   941 D BluetoothManagerService: Broadcasting onBluetoothServiceDown() to 11 receivers.
09-09 15:18:26.779   785   941 D BluetoothManagerService: unbindAndFinish(): android.bluetooth.IBluetooth$Stub$Proxy@cc6ce8e mBinding = false mUnbinding = false
09-09 15:18:26.795   785   941 D BluetoothManagerService: Sending BLE State Change: BLE_TURNING_OFF > OFF

从上面日志看也有关闭蓝牙的日志,但是并没有有设置蓝牙开关值 “Persisting Bluetooth Setting”。
所以这种情况,重启开机后蓝牙还是打开的状态。
虽然是同一个机器和系统代码,但是会出现概率蓝牙关闭的问题。

(3)Google手机上蓝牙待机的日志
谷歌原生手机日志:
09-09 15:41:03.658  1735  1735 I BluetoothManagerService: Device is shutting down.
09-09 15:41:03.665  1735  2220 D BluetoothManagerService: MESSAGE_BLUETOOTH_STATE_CHANGE: ON > TURNING_OFF
09-09 15:41:03.666  1735  2220 D BluetoothManagerService: Sending BLE State Change: ON > TURNING_OFF
09-09 15:41:03.666  1735  2220 D BluetoothManagerService: Sending State Change: ON > TURNING_OFF
09-09 15:41:03.946  1735  2220 D BluetoothManagerService: MESSAGE_BLUETOOTH_STATE_CHANGE: TURNING_OFF > BLE_ON
09-09 15:41:03.946  1735  2220 D BluetoothManagerService: Intermediate off, back to LE only mode
09-09 15:41:03.946  1735  2220 D BluetoothManagerService: Sending BLE State Change: TURNING_OFF > BLE_ON
09-09 15:41:03.947  1735  2220 D BluetoothManagerService: Broadcasting onBluetoothStateChange(false) to 31 receivers.
09-09 15:41:03.947  1735  2220 D BluetoothManagerService: Calling sendBrEdrDownCallback callbacks
09-09 15:41:03.947  1735  2220 D BluetoothManagerService: isBleAppPresent() count: 1
09-09 15:41:03.949  1735  2220 D BluetoothManagerService: Sending State Change: TURNING_OFF > OFF
09-09 15:41:04.165  1735  3502 D BluetoothManagerService: Trying to bind to profile: 1, while Bluetooth was disabled
09-09 15:41:05.936  1735  3554 D BluetoothManagerService: Trying to bind to profile: 1, while Bluetooth was disabled

同样的,从上面日志看也有关闭蓝牙的日志,但是并没有有设置蓝牙开关值 “Persisting Bluetooth Setting”。
所以这种情况,重启开机后蓝牙还是打开的状态。
谷歌手机上的蓝牙服务中关机日志比较简洁,也是没有关闭代码的。

(4)分析会设置蓝牙属性值为关闭的情况

从上面看会导致蓝牙关闭的是有调用到 disable() 方法的,没有调用到这个方法的情况都是不会设置蓝牙属性值为关闭的。

09-09 15:22:16.672   773  2893 D BluetoothManagerService: disable(): mBluetooth=android.bluetooth.IBluetooth$Stub$Proxy@d369d91, persist=true, mBinding=false
09-09 15:22:16.672   773  2893 D BluetoothManagerService: Persisting Bluetooth Setting: 0 //出现蓝牙关闭的关键日志,设置了bluetooth_on的值为0

所以在源码里面找到 disable() 方法,判断蓝牙关闭过程的情况,
去除设置蓝牙属性值设置为关闭的处理,那么下次开机蓝牙就是开启状态的值了。

3、BluetoothManagerService 去除设置蓝牙属性值为关闭的处理

Android13 、Android14 版本文件目录:
package\modules\Bluetooth\service\src\com\android\server\bluetooth\BluetoothManagerService.java


public class BluetoothManagerService extends IBluetoothManager.Stub {private static final String TAG = "BluetoothManagerService";private static final boolean DBG = true;//这个默认就是trueprivate boolean mShutdownInProgress = false; //是否为关机状态BluetoothManagerService(Context context) {//监听广播,其他相关初始化}//广播监听者private final BroadcastReceiver mReceiver = new BroadcastReceiver() {@Overridepublic void onReceive(Context context, Intent intent) {String action = intent.getAction();if (BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED.equals(action)) { //蓝牙名称变化。。。//其他蓝牙广播} else if (action.equals(Intent.ACTION_SHUTDOWN)) { //关机广播Log.i(TAG, "Device is shutting down.");mShutdownInProgress = true; //设置当前为关机状态mBluetoothLock.readLock().lock();try {mEnable = false;mEnableExternal = false;if (mBluetooth != null && (mState == BluetoothAdapter.STATE_BLE_ON)) {synchronousOnBrEdrDown(mContext.getAttributionSource());} else if (mBluetooth != null && (mState == BluetoothAdapter.STATE_ON)) {synchronousDisable(mContext.getAttributionSource());}} catch (RemoteException | TimeoutException e) {Log.e(TAG, "Unable to shutdown Bluetooth", e);} finally {mBluetoothLock.readLock().unlock();}}}};//这是一个保留的方法,不确定那里调用到了public boolean disable(AttributionSource attributionSource, boolean persist)throws RemoteException {final String packageName = attributionSource.getPackageName();final int callingUid = Binder.getCallingUid();final int callingPid = Binder.getCallingPid();if (CompatChanges.isChangeEnabled(RESTRICT_ENABLE_DISABLE, callingUid)&& !isPrivileged(callingPid, callingUid)&& !isSystem(packageName, callingUid)&& !isDeviceOwner(callingUid, packageName)&& !isProfileOwner(callingUid, packageName)) {Log.d(TAG, "disable(): not disabling - Caller is not one of: "+ "privileged | system | deviceOwner | profileOwner");return false;}if (isSatelliteModeOn()) {Log.d(TAG, "disable: not disabling - satellite mode is on.");return false;}if (DBG) {Log.d(TAG, "disable(): mBluetooth=" + mBluetooth + ", persist=" + persist+ ", mBinding=" + mBinding);}synchronized (mReceiver) {if (persist) { //设置蓝牙开关属性, BLUETOOTH_OFF 0persistBluetoothSetting(BLUETOOTH_OFF);}mEnableExternal = false;sendDisableMsg(BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST,packageName);}return true;}/***  Save the Bluetooth on/off state*/private void persistBluetoothSetting(int value) {if (DBG) {Log.d(TAG, "Persisting Bluetooth Setting: " + value);}//解决蓝牙关机过程会关闭的解决方法,这里添加关机过程就不往下走,不去设置蓝牙属性值if (mShutdownInProgress) { //change by liwenzhiLog.d(TAG, "Skip Persisting Bluetooth Setting in device shutdown process");return;}// waive WRITE_SECURE_SETTINGS permission checkfinal long callingIdentity = Binder.clearCallingIdentity();try {Settings.Global.putInt(mContext.getContentResolver(),Settings.Global.BLUETOOTH_ON, value);} finally {Binder.restoreCallingIdentity(callingIdentity);}}}

这里解决待机关机过程关闭蓝牙的对策是:
在 persistBluetoothSetting 设置蓝牙属性的时候,判断是否是关机过程,如果是关机就不去设置蓝牙属性。

那么哪里调用的 disable(XX,XX) 方法呢?
找到这个地方直接让它不调用关闭蓝牙不就可以了吗?
这里简单说一下:
BluetoothManagerService 的disable(XX,XX) 方法 是暴露的public方法,
系统代码和系统应用都是可以调用到这个方法里面,所以不好进行规避。

Android 11 或者更低的版本的 BluetoothManagerService.java 是没有 监听系统关机广播的。
文件目录:
framework\base\services\core\java\com\android\server\BluetoothManagerService.java

Android11 这个类的代码是没有监听处理 Intent.ACTION_SHUTDOWN 的。

三、其他

1、Android14 待机过程关闭蓝牙小结

分析过程主要是看 BluetoothManagerService 的处理日志,确认是否有存在关闭并设置蓝牙状态的日志。

有出现关闭蓝牙过程是正常的,主要看看有没有设置蓝牙属性 persistBluetoothSetting 的操作,如果有个这个操作那么蓝牙开关的属性会被设置为关闭。

如果要解决关机过程会设置蓝牙关闭状态的问题,那么可以在 BluetoothManagerService 里面判断蓝牙正在关闭状态不进行设置蓝牙属性就可以了。

2、蓝牙 BluetoothService 启动和相关代码

(1)蓝牙服务相关的有几个类有:
BluetoothService、BluetoothManagerService、BluetoothManager、BluetoothAdapter

估计没几个人熟悉这个关系的,这里简单梳理一下。

(2)几个蓝牙类对象的关系

这里先公布一下简单关系:

1、BluetoothService 是上层蓝牙最开始的服务,是在SystemServer 拉起系统其他应用的时候拉起的2、BluetoothManagerService 是BluetoothService 创建的时候创建的服务服务对象
具体实现是在 BluetoothManagerService 里面3、BluetoothManager 是暴露的蓝牙Manager,但是这个Manager并不是绑定 BluetoothManagerService;
BluetoothManager 只有简单的几个暴露方法,里面就有获取BluetoothAdapter对象的方法 getAdapter()4、BluetoothAdapter 是才是操作蓝牙的主要功能暴露类
BluetoothAdapter的大部分实现都是调用到 BluetoothManagerService 里面的。

蓝牙实现的功能基本都是要System api,都是要系统应用正常才能调用到相关实现。
BluetoothManager 和 BluetoothAdapter 都是应用能正常获取到的对象。
所以看Settings那些系统应用都是直接获取和使用的 BluetoothAdapter 进行蓝牙开关,设置蓝牙名称,获取蓝牙状态等实现。

详细介绍如下:

https://blog.csdn.net/wenzhi20102321/article/details/142264944

3、Android14 Settings属性断电上电不记忆问题分析解决

https://blog.csdn.net/wenzhi20102321/article/details/141303485

4、Android13 蓝牙协议属性配置详解

Android系统中蓝牙协议是否使能一般是通过一个属性值,如果这个属性值设置为false,

会导致这个协议的服务未启动,也就是说这个蓝牙功能会没有作用。

比如 Android 蓝牙传输文件协议是opp,如果opp未使能,那么整个系统是不支持蓝牙文件传输的。

在Android13之前的版本,我们可以通过 config.xml 中的 profile_supported_a2dp 属性控制蓝牙的某个协议是否使能。

但是在Android13 或者更新的版本,很多属性都需要一个新的东西控制使能蓝牙协议了,那就是蓝牙属性profile属性。

https://blog.csdn.net/wenzhi20102321/article/details/139703045

节假日快乐,身体才是革命的本钱。


http://www.ppmy.cn/ops/113755.html

相关文章

使用express或koa或nginx部署history路由模式的单页面应用

使用hash模式会有#,影响美观,所以使用history模式会是个更好的选择。 前端项目打包上线部署,可以使用下面的方式部署history模式的项目,下面以 jyH5 为例 expressjs部署 express脚手架搭建的app.js中添加如下代码: …

java通过org.eclipse.milo实现OPCUA客户端进行连接和订阅

前言 之前写过一篇关于MQTT的方式进行物理访问的文章:SpringBoot集成MQTT,WebSocket返回前端信息_springboot mqtt websocket-CSDN博客 最近又接触到OPCUA协议,想通过java试试看能不能实现。 软件 在使用java实现之前,想着有没…

蓝桥杯-基于STM32G432RBT6的LCD进阶(LCD界面切换以及高亮显示界面)

目录 一、页面切换内容详解 1.逻辑解释 2.代码详解 code.c(内含详细讲解) code.h main.c 3.效果图片展示 ​编辑 二、页面选项高亮内容详解 1.逻辑解释 2.读入数据 FIRST.第一种高亮类型 code.c(内含代码详解) code.…

详细分析Java中的ObjectMapper基本知识(附Demo)

目录 1. 基本知识2. 基本操作2.1 转换Java对象为JSON2.2 转换JSON为Java对象 3. 拓展 1. 基本知识 ObjectMapper 是 Jackson 数据处理库中的核心类之一,主要用于将 Java 对象转换为 JSON 和将 JSON 转换为 Java 对象 Jackson 是当前最流行的 JSON 处理库之一&…

生信初学者教程(五):R语言基础

文章目录 数据类型整型逻辑型字符型日期型数值型复杂数数据结构向量矩阵数组列表因子数据框ts特殊值缺失值 (NA)无穷大 (Inf)非数字 (NaN)安装R包学习材料R语言是一种用于统计计算和图形展示的编程语言和软件环境,广泛应用于数据分析、统计建模和数据可视化。1991年:R语言的最…

目标检测任务中xml标签文件修改

1. 背景 在目标检测任务中,自己有这样的需求:对于已经标注好的PascalVOC格式数据标签,想批量去掉标签中的某个分类;或者有时候想对xml标签中的某项内容进行编辑或者删除。这个该如何用python代码操作呢?自己主要使用x…

永磁同步电机谐波抑制算法(8)——基于神经网络的傻瓜式(无需知道谐波频率)谐波抑制

1.简介 前面的内容已经介绍了很多谐波抑制的方法:多同步、PIR、陷波器等等。也介绍了比较多的谐波来源:死区(5、7、11、13等次相电流谐波)、绕组不对称(基波不等幅值、3次相电流谐波)等等。 上述的方法都…

Spring Boot利用dag加速Spring beans初始化

1.什么是Dag? 有向无环图(Directed Acyclic Graph),简称DAG,是一种有向图,其中没有从节点出发经过若干条边后再回到该节点的路径。换句话说,DAG中不存在环路。这种数据结构常用于表示并解决具有依赖关系的问题。 DAG的…