android 蓝牙扫描流程,Android 9.0 Bluetooth源码分析(二)蓝牙扫描流程

1 UI

蓝牙开始扫描位于setting的 /packages/apps/Settings/src/com/android/settings/bluetooth/BluetoothPairingDetail.java 中。

void enableScanning() {

// Clear all device states before first scan

if (!mInitialScanStarted) {

if (mAvailableDevicesCategory != null) {

removeAllDevices();

}

mLocalManager.getCachedDeviceManager().clearNonBondedDevices();

mInitialScanStarted = true;

}

super.enableScanning();

}

在这里如果没有开始扫描就清除缓存中所有的设备,然后将缓存的设备中没有配对的设备清除,最后调用了父类 DeviceListPreferenceFragment 的enableScanning()方法:

@VisibleForTesting

void enableScanning() {

// LocalBluetoothAdapter already handles repeated scan requests

mLocalAdapter.startScanning(true);

mScanEnabled = true;

}

这里其实最终调用了/frameworks/base/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothAdapter的startScanning方法开始扫描。

2 framework

LocalBluetoothAdapter的startScanning方法:

public void startScanning(boolean force) {

// Only start if we're not already scanning

// 只会在没有进行扫描的时候开始扫描

if (!mAdapter.isDiscovering()) {

// 如果不是强制扫描,在SCAN_EXPIRATION_MS间隔内,只扫描一次

if (!force) {

// Don't scan more than frequently than SCAN_EXPIRATION_MS,

// unless forced

if (mLastScan + SCAN_EXPIRATION_MS > System.currentTimeMillis()) {

return;

}

// If we are playing music, don't scan unless forced.

// 播放蓝牙音乐时,不进行扫描

A2dpProfile a2dp = mProfileManager.getA2dpProfile();

if (a2dp != null && a2dp.isA2dpPlaying()) {

return;

}

}

// 开始扫描

if (mAdapter.startDiscovery()) {

mLastScan = System.currentTimeMillis();

}

}

}

这里最后调用frameworks/base/core/java/android/bluetooth/BluetoothAdapter.java的startDiscovery方法,启动扫描任务

public boolean startDiscovery() {

if (!Utils.checkCaller()) {

Log.w(TAG, "startDiscovery() - Not allowed for non-active user");

return false;

}

AdapterService service = getService();

if (service == null) return false;

return service.startDiscovery();

}

3 Bluetooth App

这里的 service.startDiscovery 属于 aidl 跨进程通信,通过 IBluetooth.aidl 调用远程服务 /packages/apps/Bluetooth/src/com/android/bluetooth/btservice/AdapterService 中的 startDiscovery 方法:

boolean startDiscovery() {

enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,

"Need BLUETOOTH ADMIN permission");

//do not allow new connections with active multicast

A2dpService a2dpService = A2dpService.getA2dpService();

if (a2dpService != null &&

a2dpService.isMulticastFeatureEnabled() &&

a2dpService.isMulticastOngoing(null)) {

Log.i(TAG,"A2dp Multicast is Ongoing, ignore discovery");

return false;

}

// 扫描中则终止操作

if (mAdapterProperties.isDiscovering()) {

Log.i(TAG,"discovery already active, ignore startDiscovery");

return false;

}

return startDiscoveryNative();

}

这里最终调用tartDiscoveryNative()方法,从 Java 层调到 JNI 层的com_android_bluetooth_btservice_AdapterService.cpp文件中的 startDiscoveryNative 方法:

static jboolean startDiscoveryNative(JNIEnv* env, jobject obj) {

ALOGV("%s:",__FUNCTION__);

jboolean result = JNI_FALSE;

if (!sBluetoothInterface) return result;

int ret = sBluetoothInterface->start_discovery();//该接口调用到hal层的配对函数

result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;

return result;

}

int ret = sBluetoothInterface->start_discovery() 这行代码调进了hal层的蓝牙协议栈中。

4 蓝牙协议栈

上面调用的start_discovery 方法位于 /system/bt/btif/src/bluetooth.cc:

static int start_discovery(void)

{

/* sanity check */ //完整性检查

if (interface_ready() == FALSE)

return BT_STATUS_NOT_READY;

return btif_dm_start_discovery();

}

你可能感兴趣的:(android,蓝牙扫描流程)