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

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

文章目录

一、前言

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;//这个默认就是true

    private boolean mShutdownInProgress = false; //是否为关机状态

    BluetoothManagerService(Context context) {
    //监听广播,其他相关初始化
    }

    //广播监听者
   private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        public 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 0
                persistBluetoothSetting(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 liwenzhi
            Log.d(TAG, "Skip Persisting Bluetooth Setting in device shutdown process");
            return;
        }

        // waive WRITE_SECURE_SETTINGS permission check
        final 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

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

相关推荐
凯文的内存1 小时前
Android14 OTA升级速度过慢问题解决方案
android·ota·update engine·系统升级·virtual ab
VinRichard1 小时前
Android 常用三方库
android
Aileen_0v02 小时前
【玩转OCR | 腾讯云智能结构化OCR在图像增强与发票识别中的应用实践】
android·java·人工智能·云计算·ocr·腾讯云·玩转腾讯云ocr
江上清风山间明月5 小时前
Flutter DragTarget拖拽控件详解
android·flutter·ios·拖拽·dragtarget
debug_cat8 小时前
AndroidStudio Ladybug中编译完成apk之后定制名字kts复制到指定目录
android·android studio
编程洪同学12 小时前
Spring Boot 中实现自定义注解记录接口日志功能
android·java·spring boot·后端
氤氲息14 小时前
Android 底部tab,使用recycleview实现
android
Clockwiseee14 小时前
PHP之伪协议
android·开发语言·php
小林爱14 小时前
【Compose multiplatform教程08】【组件】Text组件
android·java·前端·ui·前端框架·kotlin·android studio
小何开发16 小时前
Android Studio 安装教程
android·ide·android studio