【车机蓝牙】【冷启动自动连接蓝牙设备】【休眠唤醒后自动连接蓝牙设备】【开关蓝牙后自动连接】

1. 背景

当车机上电或者休眠唤醒后 或者 手动开关蓝牙后, 发现我们的车机会自动去连接我们已经配对的设备。 那这块逻辑在哪里? 今天帮助各位看官老爷们梳理一下。

2. Carserver

自动连接蓝牙设备, 从问题描述来看, 是蓝牙的上层业务逻辑开发。 所以这个实现 肯定不会在我们的 com.android.bluetooth 蓝牙核心服务中来处理。 在车机中我们将他归类到了 carserver 中来处理。

代码路径在:

  • android/packages/services/Car

car server 中有关蓝牙的代码如下:

在这里插入图片描述

BluetoothConnectionRetryManager.java  
BluetoothPowerPolicy.java            
CarBluetoothService.java        
FastPairAdvertiser.java
BluetoothDeviceConnectionPolicy.java  
BluetoothProfileInhibitManager.java  
CarBluetoothUserService.java    
FastPairGattServer.java
BluetoothDeviceManager.java           
BluetoothUtils.java                  
FastPairAccountKeyStorage.java  
FastPairProvider.java

接下来我们将围绕如下疑问来讨论:

  1. Carservice 中有关 bluetooth 是怎么初始化的?
  2. 车机冷启动 和 开关蓝牙 自动连接触发时机?
  3. 默认aosp 中自动连接的逻辑是什么?
  4. 自动连接是如何停止的?
  5. 自动连接相关log的 tag 汇总
  6. 小结

2.1 CarBluetoothService 和CarPerUserServiceHelper 创建和初始化过程

  • service/src/com/android/car/CarServiceImpl.java
public class CarServiceImpl extends ProxiedService {
    public static final String CAR_SERVICE_INIT_TIMING_TAG = "CAR.InitTiming";


    @Override
    public void onCreate() {

        // 创建 ICarImpl 对象
        mICarImpl = new ICarImpl(this,
                getBuiltinPackageContext(),
                mVehicle,
                SystemInterface.Builder.defaultSystemInterface(this).build(),
                mVehicleInterfaceName);
        // 调用对应的 init 函数
        mICarImpl.init();

	// ICarImpl 构造函数
    ICarImpl(...) {
        
        // 这里 创建了 CarBluetoothService 对象
        mCarPerUserServiceHelper = constructWithTrace(
                t, CarPerUserServiceHelper.class,
                () -> new CarPerUserServiceHelper(serviceContext, mCarUserService), allServices);
        mCarBluetoothService = constructWithTrace(t, CarBluetoothService.class,
                () -> new CarBluetoothService(serviceContext, mCarPerUserServiceHelper),
                allServices);
        
        
        
        }




    private <T extends CarSystemService> T constructWithTrace(LimitedTimingsTraceLog t,
            Class<T> cls, Callable<T> callable, List<CarSystemService> allServices) {
        t.traceBegin(cls.getSimpleName());
        T constructed;
        try {
            constructed = callable.call();
            CarLocalServices.addService(cls, constructed);
        } catch (Exception e) {
            throw new RuntimeException("Crash while constructing:" + cls.getSimpleName(), e);
        } finally {
            t.traceEnd();
        }
        // 这里将 CarBluetoothService 对象加入到 allServices 中
        allServices.add(constructed);
        return constructed;
    }


    void init() {

        for (CarSystemService service : mAllServices) {
            // 调用  CarPerUserServiceHelper 和 CarBluetoothService 对象的 init 函数
            service.init();

        }
        
        mCarOemService.onInitComplete();
    }

  1. 从上面的代码中我们可以知道 在 CarService 服务启动时, 在 onCreate 函数中, 我们会 创建一个 ICarImpl 对象,

    • 在 ICarImpl 构造中 创建了 CarPerUserServiceHelper 和 CarBluetoothService 对象,并且将服务加入到了 allServices 中。
  2. 在 CarService.onCreate 中同时调用了 mICarImpl.init, 此时才会调用之前加入 allServices 中 服务的init 函数。

    • 此时 CarPerUserServiceHelper.init 和 CarBluetoothService.init 函数才会调用

2.1.1 CarPerUserServiceHelper.init 做了那些事情

  • service/src/com/android/car/CarPerUserServiceHelper.java
    public void init() {
        synchronized (mServiceBindLock) {
            bindToCarPerUserService();
        }
    }
  • 这里很明确,只做了一件事情, 那就是 绑定 CarPerUserServiceHelper bind com.android.car.CarPerUserService 服务

当我们 carserver bind com.android.car.CarPerUserService 成功后,


    public static final String CAR_USER_PER_SERVICE_CLASS = "com.android.car.CarPerUserService";

    private void bindToCarPerUserService() {
        // This crosses both process and package boundary.
        Intent startIntent = BuiltinPackageDependency.addClassNameToIntent(mContext, new Intent(),
                BuiltinPackageDependency.CAR_USER_PER_SERVICE_CLASS);
        synchronized (mServiceBindLock) {
            mBound = true;
            boolean bindSuccess = mContext.bindServiceAsUser(startIntent, mUserServiceConnection,
                    mContext.BIND_AUTO_CREATE, UserHandle.CURRENT);

        }
    }
  • 上面是 CarPerUserServiceHelper bind com.android.car.CarPerUserService 的地方。 通过 bindServiceAsUser 去bind 这个 服务。

当我们 bind 服务成功后:

    private final ServiceConnection mUserServiceConnection = new ServiceConnection() {

        public void onServiceConnected(ComponentName componentName, IBinder service) {
            mHandler.post(() -> {
                List<ServiceCallback> callbacks;
                if (DBG) {
                    Slogf.d(TAG, "Connected to User Service");
                }
                mCarPerUserService = ICarPerUserService.Stub.asInterface(service);
                if (mCarPerUserService != null) {
                    synchronized (mServiceBindLock) {
                        // copy the callbacks
                        callbacks = new ArrayList<>(mServiceCallbacks);
                    }
                    // call them
                    for (ServiceCallback callback : callbacks) {
                    // 这里调用所有注册进 mServiceCallbacks 的回调
                        callback.onServiceConnected(mCarPerUserService);
                    }
                }
            });
        }
  • 从上述的代码中我们知道, 当 CarPerUserServiceHelper 绑定com.android.car.CarPerUserService 服务成功后,就会触发调用 callback.onServiceConnected , 其实这里调用的是 CarBluetoothService的mUserServiceCallback。

这里的 mServiceCallbacks 是如何加入的,通过 调用 registerServiceCallback

    public void registerServiceCallback(ServiceCallback listener) {
        if (listener != null) {
            if (DBG) {
                Slogf.d(TAG, "Registering CarPerUserService Listener");
            }
            synchronized (mServiceBindLock) {
                mServiceCallbacks.add(listener);
            }
        }
    }

2.1.2 CarBluetoothService.init 做了那些事情

  • service/src/com/android/car/bluetooth/CarBluetoothService.java
    public void init() {
        if (DBG) {
            Slogf.d(TAG, "init()");
        }
        // 这里直接是向 CarPerUserServiceHelper 中注册了 mUserServiceCallback
        mUserServiceHelper.registerServiceCallback(mUserServiceCallback);
    }
  • CarBluetoothService.init 中只是向 CarPerUserServiceHelper 中注册了 mUserServiceCallback

  • 当 CarPerUserServiceHelper 绑定com.android.car.CarPerUserService 服务成功后,就会触发调用 callback.onServiceConnected , 其实这里调用的是 CarBluetoothService的mUserServiceCallback。


    private final CarPerUserServiceHelper.ServiceCallback mUserServiceCallback =
            new CarPerUserServiceHelper.ServiceCallback() {
        @Override
        public void onServiceConnected(ICarPerUserService carPerUserService) {
            synchronized (mPerUserLock) {

				// 主要调用这里
                // Create new objects with our new set of profile proxies
                initializeUserLocked();
            }
        }
  • 在回调中主要是调用 initializeUserLocked
    private void initializeUserLocked() {
		// 创建 BluetoothDeviceManager 对象,并调用start 函数
        createBluetoothDeviceManagerLocked();

        mBluetoothDeviceConnectionPolicy = null;
        if (mUseDefaultConnectionPolicy) {
	        // 创建 BluetoothDeviceConnectionPolicy 对象并调用 init 函数
            createBluetoothDeviceConnectionPolicyLocked();
        }
        
    }

    private void createBluetoothDeviceManagerLocked() {
        // 创建 BluetoothDeviceManager 对象
        mDeviceManager = BluetoothDeviceManager.create(mContext);
        // 并调用 BluetoothDeviceManager.start
        mDeviceManager.start();
    }

    private void createBluetoothDeviceConnectionPolicyLocked() {

        mBluetoothDeviceConnectionPolicy = BluetoothDeviceConnectionPolicy.create(mContext,
                mUserId, this);
        mBluetoothDeviceConnectionPolicy.init();
    }

也就是说:

  • 当 CarPerUserServiceHelper 绑定com.android.car.CarPerUserService 服务成功后,就会触发调用 CarBluetoothService的mUserServiceCallback。

  • 在 mUserServiceCallback 中我们会去创建 BluetoothDeviceManager 对象并调用 start 函数, 同时会创建 BluetoothDeviceConnectionPolicy对象并调用 init 函数。

  • 这里最主要是 给 CarBluetoothService 中 mDeviceManager 赋值和mBluetoothDeviceConnectionPolicy 赋值,并调用 init 函数

2.2 车机冷启动后自动重连触发时机?

上面分析中我们知道 :

  • 当 CarPerUserServiceHelper 绑定com.android.car.CarPerUserService 服务成功后,就会触发调用 CarBluetoothService的mUserServiceCallback。
  • 在 mUserServiceCallback 中我们会去创建 BluetoothDeviceManager 对象并调用 start 函数, 同时会创建 BluetoothDeviceConnectionPolicy对象并调用 init 函数。

现在我们来看一下 BluetoothDeviceConnectionPolicy.init 函数中做了啥

  • service/src/com/android/car/bluetooth/BluetoothDeviceConnectionPolicy.java
    public void init() {

		// 这里会注册
        IntentFilter profileFilter = new IntentFilter();
        profileFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
        UserHandle currentUser = UserHandle.of(ActivityManager.getCurrentUser());
        mUserContext = mContext.createContextAsUser(currentUser, /* flags= */ 0);
	    // 注册一个广播
        mUserContext.registerReceiver(mBluetoothBroadcastReceiver, profileFilter);
        mCarHelper.init();

		// 如果 此时蓝牙时打开的状态, 那就直接触发 自动连接
        if (mBluetoothAdapter.getState() == BluetoothAdapter.STATE_ON) {

            connectDevices();
        }
    }
  • 在 BluetoothDeviceConnectionPolicy.init 函数 中做:
    • 注册 BluetoothAdapter.ACTION_STATE_CHANGED 广播
    • 如果此时蓝牙时打开的(蓝牙服务启动) 那就通过 connectDevices() 来触发自动连接。
    • 如果此时蓝牙没有打开, 就直接返回了, 当蓝牙在后续打开之后, 会通过 广播回调来触发 自动连接。

2.3 后续开关蓝牙后如何触发自动连接?

在 BluetoothDeviceConnectionPolicy.init 函数 中做:
- 注册 BluetoothAdapter.ACTION_STATE_CHANGED 广播
- 如果此时蓝牙时打开的(蓝牙服务启动) 那就通过 connectDevices() 来触发自动连接。
- 如果此时蓝牙没有打开, 就直接返回了, 当蓝牙在后续打开之后, 会通过 广播回调来触发 自动连接。

  • service/src/com/android/car/bluetooth/BluetoothDeviceConnectionPolicy.java
private class BluetoothBroadcastReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) {
                int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1);
                if (DBG) {
                    Slogf.d(TAG, "Bluetooth Adapter state changed: %s",
                            BluetoothUtils.getAdapterStateName(state));
                }
                if (state == BluetoothAdapter.STATE_ON) {
                    connectDevices();
                }
            }
        }
    }

2.4 默认aosp 中自动连接的逻辑是?

2.4.1 connectDevices 函数分析

看到这里我们就清楚 自动重连 是通过 connectDevices 来触发的。

  • service/src/com/android/car/bluetooth/BluetoothDeviceConnectionPolicy.java
    public void connectDevices() {
        mCarBluetoothService.connectDevices();
    }
  • service/src/com/android/car/bluetooth/CarBluetoothService.java
    public void connectDevices() {
        enforceBluetoothAdminPermission();
        if (DBG) {
            Slogf.d(TAG, "Connect devices for each profile");
        }
        synchronized (mPerUserLock) {
            if (mDeviceManager != null) {
                mDeviceManager.beginAutoConnecting();
            }
        }
    }

  • service/src/com/android/car/bluetooth/BluetoothDeviceManager.java
    public void beginAutoConnecting() {
        if (DBG) {
            Slogf.d(TAG, "Request to begin auto connection process");
        }
        synchronized (mAutoConnectLock) {
            if (isAutoConnecting()) {
                if (DBG) {
                    Slogf.d(TAG, "Auto connect requested while we are already auto connecting");
                }
                return;
            }
            if (mBluetoothAdapter.getState() != BluetoothAdapter.STATE_ON) {
                if (DBG) {
                    Slogf.d(TAG, "Bluetooth Adapter is not on, cannot connect devices");
                }
                return;
            }

            mAutoConnectingDevices = getDeviceListSnapshot();
            if (mAutoConnectingDevices.isEmpty()) {
                if (DBG) {
                    Slogf.d(TAG, "No saved devices to auto-connect to.");
                }
                cancelAutoConnecting();
                return;
            }
            mConnecting = true;
            mAutoConnectPriority = 0;
        }
        autoConnectWithTimeout();
    }
  • 从上面的代码中, 我们清楚, 我们的 自动重连逻辑是在 BluetoothDeviceManager 类中管理的。

所以我们只需要着重分析 BluetoothDeviceManager 中的逻辑即可。

2.4.2 BluetoothDeviceManager 对应自动重连逻辑分析

  • service/src/com/android/car/bluetooth/BluetoothDeviceManager.java
    public void beginAutoConnecting() {
        if (DBG) {
            Slogf.d(TAG, "Request to begin auto connection process");
        }
        synchronized (mAutoConnectLock) {
            if (isAutoConnecting()) {
                if (DBG) {
                    Slogf.d(TAG, "Auto connect requested while we are already auto connecting");
                }
                // 如果此时正在做自动连接 , 那这里直接返回
                return;
            }
            if (mBluetoothAdapter.getState() != BluetoothAdapter.STATE_ON) {
                if (DBG) {
                    Slogf.d(TAG, "Bluetooth Adapter is not on, cannot connect devices");
                }
                // 这里再次判断蓝牙是否打开, 如果此时蓝牙时关闭的,直接返回
                return;
            }

            mAutoConnectingDevices = getDeviceListSnapshot(); // 这里会去拿  一个 已经配对设备的 快照(复制一份)
            if (mAutoConnectingDevices.isEmpty()) {
                if (DBG) {
                    Slogf.d(TAG, "No saved devices to auto-connect to.");
                }
                // 如果 没有配对设备,取消自动连接 返回
                cancelAutoConnecting();
                return;
            }
            // 设置自动连接的标志,标识正在自动连接
            mConnecting = true;
            // 初始化 自动连接设备的标号为0, 从  mAutoConnectingDevices 列表中第一个设备开始 尝试连接
            mAutoConnectPriority = 0;
        }
        // 真正的连接在这里处理
        autoConnectWithTimeout();
    }
    private void autoConnectWithTimeout() {
        synchronized (mAutoConnectLock) {
            if (!isAutoConnecting()) {
                if (DBG) {
                    Slogf.d(TAG,
                            "Autoconnect process was cancelled, skipping connecting next device");
                }
                // 如果此时发现取消了自动连接,那这里直接放弃
                return;
            }
            if (mAutoConnectPriority < 0 || mAutoConnectPriority >= mAutoConnectingDevices.size()) {

                // 判断 mAutoConnectPriority 的合法性, 
                // mAutoConnectPriority 不能越界。 最大就是 mAutoConnectingDevices.size
                return;
            }

			// 先从 序号0 中取出 第一个需要连接的设备
            BluetoothDevice device = mAutoConnectingDevices.get(mAutoConnectPriority);
            if (DBG) {
                Slogf.d(TAG, "Auto connecting (%d) device: %s", mAutoConnectPriority, device);
            }

            mHandler.post(() -> {
                initializeAutoConnectingDeviceProfiles();
		        // 这里会异步 触发对这个设备的连接
                int connectStatus = connect(device);
                if (connectStatus != BluetoothStatusCodes.SUCCESS) {
                    Slogf.w(TAG,
                            "Connection attempt immediately failed, moving to the next device");
                    // 如果立即连接这个失败失败,会切换连接下一个设备
                    continueAutoConnecting();
                }
            });

			// 8s 内如果没有人取消这个AUTO_CONNECT_TOKEN任务,  将执行这个 去继续连接下一个。 
            mHandler.postDelayed(() -> {
                Slogf.w(TAG, "Auto connect process has timed out connecting to %s", device);
                continueAutoConnecting();
            }, AUTO_CONNECT_TOKEN, AUTO_CONNECT_TIMEOUT_MS);
        }
    }

	// 8s
    private static final int AUTO_CONNECT_TIMEOUT_MS = 8000;
  • 从 autoConnectWithTimeout 的备注来看:
    • 我们首先会 从 mAutoConnectingDevices(要连接设备的list) 中取出 第 mAutoConnectPriority 个设备,来发起连接。
    • 如果第 mAutoConnectPriority 个设备,连接立马返回错误,将立即触发 continueAutoConnecting 连接(发起下一个设备连接),
    • 如果第 mAutoConnectPriority 个设备,连接没有返回失败,那么 将设定一个 8s 的定时任务。
      • 8s 后将执行这个任务。继续触发 continueAutoConnecting 连接(发起下一个设备连接),

2.5 自动连接是如何停止的?

2.5.1 遍历完所有的设备后停止

  • continueAutoConnecting 函数中 mAutoConnectPriority 每次重连都会 ++ , 当 mAutoConnectPriority == mAutoConnectingDevices.size 时,表示此时 已经将 所以已经配对的设备都尝试连接完成了。 此时可以终止 自动连接了。
    private void continueAutoConnecting() {
        if (DBG) {
            Slogf.d(TAG, "Continue auto-connect process on next device");
        }
        synchronized (mAutoConnectLock) {
            if (!isAutoConnecting()) {
                if (DBG) {
                    Slogf.d(TAG, "Autoconnect process was cancelled, no need to continue.");
                }
                return;
            }
            mHandler.removeCallbacksAndMessages(AUTO_CONNECT_TOKEN);
            mAutoConnectPriority++;
            if (mAutoConnectPriority >= mAutoConnectingDevices.size()) {
                if (DBG) {
                    Slogf.d(TAG, "No more devices to connect to");
                }
                cancelAutoConnecting();
                return;
            }
        }
        autoConnectWithTimeout();
    }
  • 也就是说原生 aosp 的自动连接, 是 间隔 8s 下发 下一个设备的连接。 也就是说。 会把所有 mAutoConnectingDevices 中的设备, 都连接一遍。 并不是,其中一个设备连接成功后,就停止 自动连接。

2.6 自动连接相关log的 tag 汇总

我们可以通过过滤如下 log tag 来查看对应的逻辑:

CAR.BluetoothDeviceManager|CarBluetoothService|BluetoothDeviceConnectionPolicy

在这里插入图片描述

2.7 自动连接小结

  1. 在 CarService 服务启动时, 在 onCreate 函数中, 我们会 创建一个 ICarImpl 对象,

    • 在 ICarImpl 构造中 创建了 CarPerUserServiceHelper 和 CarBluetoothService 对象,并且将服务加入到了 allServices 中。
  2. 在 CarService.onCreate 中同时调用了 mICarImpl.init, 此时才会调用之前加入 allServices 中 服务的init 函数。

    • 此时 CarPerUserServiceHelper.init 和 CarBluetoothService.init 函数才会调用
    • CarPerUserServiceHelper.init 中 绑定com.android.car.CarPerUserService 服务
    • 当 CarPerUserServiceHelper 绑定com.android.car.CarPerUserService 服务成功后,就会触发调用 callback.onServiceConnected , 其实这里调用的是 CarBluetoothService的mUserServiceCallback,主要是 给 CarBluetoothService 中 mDeviceManager 和mBluetoothDeviceConnectionPolicy 赋值,并调用 init 函数
  3. 在 BluetoothDeviceConnectionPolicy.init 函数 中做:

    • 注册 BluetoothAdapter.ACTION_STATE_CHANGED 广播
    • 如果此时蓝牙是打开的(蓝牙服务启动) 那就通过 connectDevices() 来触发自动连接。
    • 如果此时蓝牙没有打开, 就直接返回了, 当蓝牙在后续打开之后, 会通过 广播回调来触发 自动连接。
  4. connectDevices 会触发到BluetoothDeviceManager 中,是真正实现 自动重连的地方。

    • 在 autoConnectWithTimeout 中执行重连逻辑:
      • 我们首先会 从 mAutoConnectingDevices(要连接设备的list) 中取出 第 mAutoConnectPriority 个设备,来发起连接。
      • 如果第 mAutoConnectPriority 个设备,连接立马返回错误,将立即触发 continueAutoConnecting 连接(发起下一个设备连接),
      • 如果第 mAutoConnectPriority 个设备,连接没有返回失败,那么 将设定一个 8s 的定时任务。
        • 8s 后将执行这个任务。继续触发 continueAutoConnecting 连接(发起下一个设备连接),
      • 直到将 mAutoConnectingDevices 中所有设备都连接完, 停止自动重连。

3. Bluetooth

接下来我们去看一下是如何 告知 bluetooth 服务去触发连接的。

  • service/src/com/android/car/bluetooth/BluetoothDeviceManager.java
    在 BluetoothDeviceManager 中调用 connect
    private void autoConnectWithTimeout() {

            mHandler.post(() -> {
                initializeAutoConnectingDeviceProfiles();
                logd("autoConnectWithTimeout connect.");
                int connectStatus = connect(device);
            });

        }
    }

    private int connect(BluetoothDevice device) {
        return device.connect();
    }

  • 直接调用 BluetoothDevice.connect

3.1 BluetoothDevice.connect

  • android/packages/modules/Bluetooth/framework/java/android/bluetooth/BluetoothDevice.java
    public @ConnectionReturnValues int connect() {

        final IBluetooth service = getBluetooth();

		service.connectAllEnabledProfiles(this, mAttributionSource, recv);

        return defaultValue;
    }
  • 通过 getBluetooth 找到 AdapterService 调用 connectAllEnabledProfiles 去触发连接。

3.2 触发 bluetooth服务去执行 connectAllSupportedProfiles

  • packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/AdapterService.java
    void connectAllSupportedProfiles(BluetoothDevice device) {
        int numProfilesConnected = 0;

        // All profile toggles disabled, so connects all supported profiles
        if (mA2dpService != null && isProfileSupported(device, BluetoothProfile.A2DP)) {
            Log.i(TAG, "connectAllSupportedProfiles: Connecting A2dp");
            // Set connection policy also connects the profile with CONNECTION_POLICY_ALLOWED
            mA2dpService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
            numProfilesConnected++;
        }
        if (mA2dpSinkService != null && isProfileSupported(
                device, BluetoothProfile.A2DP_SINK)) {
            Log.i(TAG, "connectAllSupportedProfiles: Connecting A2dp Sink");
            mA2dpSinkService.setConnectionPolicy(device,
                    BluetoothProfile.CONNECTION_POLICY_ALLOWED);
            numProfilesConnected++;
        }
        if (mHeadsetService != null && isProfileSupported(
                device, BluetoothProfile.HEADSET)) {
            Log.i(TAG, "connectAllSupportedProfiles: Connecting Headset Profile");
            mHeadsetService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
            numProfilesConnected++;
        }
        if (mHeadsetClientService != null && isProfileSupported(
                device, BluetoothProfile.HEADSET_CLIENT)) {
            Log.i(TAG, "connectAllSupportedProfiles: Connecting HFP");
            mHeadsetClientService.setConnectionPolicy(device,
                    BluetoothProfile.CONNECTION_POLICY_ALLOWED);
            numProfilesConnected++;
        }
        if (mMapClientService != null && isProfileSupported(
                device, BluetoothProfile.MAP_CLIENT)) {
            Log.i(TAG, "connectAllSupportedProfiles: Connecting MAP");
            mMapClientService.setConnectionPolicy(device,
                    BluetoothProfile.CONNECTION_POLICY_ALLOWED);
            numProfilesConnected++;
        }
        if (mHidHostService != null && isProfileSupported(
                device, BluetoothProfile.HID_HOST)) {
            Log.i(TAG, "connectAllSupportedProfiles: Connecting Hid Host Profile");
            mHidHostService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
            numProfilesConnected++;
        }
        if (mPanService != null && isProfileSupported(
                device, BluetoothProfile.PAN)) {
            Log.i(TAG, "connectAllSupportedProfiles: Connecting Pan Profile");
            mPanService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
            numProfilesConnected++;
        }
        if (mPbapClientService != null && isProfileSupported(
                device, BluetoothProfile.PBAP_CLIENT)) {
            Log.i(TAG, "connectAllSupportedProfiles: Connecting Pbap");
            mPbapClientService.setConnectionPolicy(device,
                    BluetoothProfile.CONNECTION_POLICY_ALLOWED);
            numProfilesConnected++;
        }
        if (mHearingAidService != null && isProfileSupported(
                device, BluetoothProfile.HEARING_AID)) {
            if (mHapClientService != null && isProfileSupported(
                    device, BluetoothProfile.HAP_CLIENT)) {
                Log.i(TAG, "connectAllSupportedProfiles: Hearing Access Client Profile is enabled"
                        + " at the same time with Hearing Aid Profile, ignore Hearing Aid Profile");
            } else {
                Log.i(TAG, "connectAllSupportedProfiles: Connecting Hearing Aid Profile");
                mHearingAidService.setConnectionPolicy(device,
                    BluetoothProfile.CONNECTION_POLICY_ALLOWED);
                numProfilesConnected++;
            }
        }
        if (mHapClientService != null && isProfileSupported(
                device, BluetoothProfile.HAP_CLIENT)) {
            Log.i(TAG, "connectAllSupportedProfiles: Connecting Hearing Access Client Profile");
            mHapClientService.setConnectionPolicy(device,
                    BluetoothProfile.CONNECTION_POLICY_ALLOWED);
            numProfilesConnected++;
        }
        if (mVolumeControlService != null && isProfileSupported(
                device, BluetoothProfile.VOLUME_CONTROL)) {
            Log.i(TAG, "connectAllSupportedProfiles: Connecting Volume Control Profile");
            mVolumeControlService.setConnectionPolicy(device,
                    BluetoothProfile.CONNECTION_POLICY_ALLOWED);
            numProfilesConnected++;
        }
        if (mCsipSetCoordinatorService != null
                && isProfileSupported(
                device, BluetoothProfile.CSIP_SET_COORDINATOR)) {
            Log.i(TAG, "connectAllSupportedProfiles: Connecting Coordinated Set Profile");
            mCsipSetCoordinatorService.setConnectionPolicy(
                    device, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
            numProfilesConnected++;
        }
        if (mLeAudioService != null && isProfileSupported(
                device, BluetoothProfile.LE_AUDIO)) {
            Log.i(TAG, "connectAllSupportedProfiles: Connecting LeAudio profile (BAP)");
            mLeAudioService.setConnectionPolicy(device,
                    BluetoothProfile.CONNECTION_POLICY_ALLOWED);
            numProfilesConnected++;
        }
        if (mBassClientService != null && isProfileSupported(
                device, BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT)) {
            Log.i(TAG, "connectAllSupportedProfiles: Connecting LE Broadcast Assistant Profile");
            mBassClientService.setConnectionPolicy(device,
                    BluetoothProfile.CONNECTION_POLICY_ALLOWED);
            numProfilesConnected++;
        }
        if (mBatteryService != null && isProfileSupported(
                device, BluetoothProfile.BATTERY)) {
            Log.i(TAG, "connectAllSupportedProfiles: Connecting Battery Service");
            mBatteryService.setConnectionPolicy(device,
                    BluetoothProfile.CONNECTION_POLICY_ALLOWED);
            numProfilesConnected++;
        }

        Log.i(TAG, "connectAllSupportedProfiles: Number of Profiles Connected: "
                + numProfilesConnected);
    }

  • 最终调用到这里去连接 这个设备,允许连接的所有协议。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值