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
接下来我们将围绕如下疑问来讨论:
- Carservice 中有关 bluetooth 是怎么初始化的?
- 车机冷启动 和 开关蓝牙 自动连接触发时机?
- 默认aosp 中自动连接的逻辑是什么?
- 自动连接是如何停止的?
- 自动连接相关log的 tag 汇总
- 小结
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();
}
-
从上面的代码中我们可以知道 在 CarService 服务启动时, 在 onCreate 函数中, 我们会 创建一个 ICarImpl 对象,
- 在 ICarImpl 构造中 创建了 CarPerUserServiceHelper 和 CarBluetoothService 对象,并且将服务加入到了 allServices 中。
-
在 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 自动连接小结
-
在 CarService 服务启动时, 在 onCreate 函数中, 我们会 创建一个 ICarImpl 对象,
- 在 ICarImpl 构造中 创建了 CarPerUserServiceHelper 和 CarBluetoothService 对象,并且将服务加入到了 allServices 中。
-
在 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 函数
-
在 BluetoothDeviceConnectionPolicy.init 函数 中做:
- 注册 BluetoothAdapter.ACTION_STATE_CHANGED 广播
- 如果此时蓝牙是打开的(蓝牙服务启动) 那就通过 connectDevices() 来触发自动连接。
- 如果此时蓝牙没有打开, 就直接返回了, 当蓝牙在后续打开之后, 会通过 广播回调来触发 自动连接。
-
connectDevices 会触发到BluetoothDeviceManager 中,是真正实现 自动重连的地方。
- 在 autoConnectWithTimeout 中执行重连逻辑:
- 我们首先会 从 mAutoConnectingDevices(要连接设备的list) 中取出 第 mAutoConnectPriority 个设备,来发起连接。
- 如果第 mAutoConnectPriority 个设备,连接立马返回错误,将立即触发 continueAutoConnecting 连接(发起下一个设备连接),
- 如果第 mAutoConnectPriority 个设备,连接没有返回失败,那么 将设定一个 8s 的定时任务。
- 8s 后将执行这个任务。继续触发 continueAutoConnecting 连接(发起下一个设备连接),
- 直到将 mAutoConnectingDevices 中所有设备都连接完, 停止自动重连。
- 在 autoConnectWithTimeout 中执行重连逻辑:
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);
}
- 最终调用到这里去连接 这个设备,允许连接的所有协议。