当蓝牙配对后会发送ACTION_PAIRING_REQUEST广播,通知APP蓝牙配对信息(配对码),具体流程如下:
蓝牙芯片通过UART到BT Driver然后再到BT 协议栈,蓝牙协议栈由BTIF、BTIF AV、BTU、BTA、BTE、BTM、HCI组成,我们直接从BTA开始:
//packages/modules/Bluetooth/system/bta/dm/bta_dm_act.cc
static uint8_t bta_dm_pin_cback(const RawAddress& bd_addr, DEV_CLASS dev_class,
const tBTM_BD_NAME bd_name, bool min_16_digit) {
if (!bta_dm_cb.p_sec_cback) return BTM_NOT_AUTHORIZED;
/* If the device name is not known, save bdaddr and devclass and initiate a
* name request */
if (bd_name[0] == 0) {
bta_dm_cb.pin_evt = BTA_DM_PIN_REQ_EVT;
bta_dm_cb.pin_bd_addr = bd_addr;
BTA_COPY_DEVICE_CLASS(bta_dm_cb.pin_dev_class, dev_class);
if ((BTM_ReadRemoteDeviceName(bd_addr, bta_dm_pinname_cback,
BT_TRANSPORT_BR_EDR)) == BTM_CMD_STARTED)
return BTM_CMD_STARTED;
APPL_TRACE_WARNING(
" bta_dm_pin_cback() -> Failed to start Remote Name Request ");
}
tBTA_DM_SEC sec_event = {.pin_req = {
.bd_addr = bd_addr,
}};
BTA_COPY_DEVICE_CLASS(sec_event.pin_req.dev_class, dev_class);
strlcpy((char*)sec_event.pin_req.bd_name, (char*)bd_name, BD_NAME_LEN + 1);
sec_event.pin_req.min_16_digit = min_16_digit;
bta_dm_cb.p_sec_cback(BTA_DM_PIN_REQ_EVT, &sec_event);
return BTM_CMD_STARTED;
}
bta_dm_cb p_sec_cback
调用bta_dm_cb的p_sec_cback函数发送BTA_DM_PIN_REQ_EVT消息,消息在btif_dm_upstreams_evt中处理:
//packages/modules/Bluetooth/system/btif/src/btif_dm.cc
static void btif_dm_upstreams_evt(uint16_t event, char* p_param) {
tBTA_DM_SEC* p_data = (tBTA_DM_SEC*)p_param;
RawAddress bd_addr;
BTIF_TRACE_EVENT("%s: ev: %s", __func__, dump_dm_event(event));
switch (event) {
case BTA_DM_PIN_REQ_EVT:
btif_dm_pin_req_evt(&p_data->pin_req);
break;
case BTA_DM_AUTH_CMPL_EVT:
btif_dm_auth_cmpl_evt(&p_data->auth_cmpl);
break;
case BTA_DM_BOND_CANCEL_CMPL_EVT:
if (is_bonding_or_sdp()) {
bd_addr = pairing_cb.bd_addr;
btm_set_bond_type_dev(pairing_cb.bd_addr,
tBTM_SEC_DEV_REC::BOND_TYPE_UNKNOWN);
bond_state_changed((bt_status_t)p_data->bond_cancel_cmpl.result,
bd_addr, BT_BOND_STATE_NONE);
}
break;
case BTA_DM_SP_CFM_REQ_EVT:
btif_dm_ssp_cfm_req_evt(&p_data->cfm_req);
break;
case BTA_DM_SP_KEY_NOTIF_EVT:
btif_dm_ssp_key_notif_evt(&p_data->key_notif);
break;
case BTA_DM_DEV_UNPAIRED_EVT:
bd_addr = p_data->link_down.bd_addr;
btm_set_bond_type_dev(p_data->link_down.bd_addr,
tBTM_SEC_DEV_REC::BOND_TYPE_UNKNOWN);
/*special handling for HID devices */
#if (defined(BTA_HH_INCLUDED) && (BTA_HH_INCLUDED == TRUE))
btif_hh_remove_device(bd_addr);
#endif
#if (defined(BTA_HD_INCLUDED) && (BTA_HD_INCLUDED == TRUE))
btif_hd_remove_device(bd_addr);
#endif
btif_hearing_aid_get_interface()->RemoveDevice(bd_addr);
if (bluetooth::csis::CsisClient::IsCsisClientRunning())
btif_csis_client_get_interface()->RemoveDevice(bd_addr);
if (LeAudioClient::IsLeAudioClientRunning())
btif_le_audio_get_interface()->RemoveDevice(bd_addr);
if (VolumeControl::IsVolumeControlRunning()) {
btif_volume_control_get_interface()->RemoveDevice(bd_addr);
}
btif_storage_remove_bonded_device(&bd_addr);
bond_state_changed(BT_STATUS_SUCCESS, bd_addr, BT_BOND_STATE_NONE);
break;
case BTA_DM_LINK_UP_EVT:
bd_addr = p_data->link_up.bd_addr;
BTIF_TRACE_DEBUG("BTA_DM_LINK_UP_EVT. Sending BT_ACL_STATE_CONNECTED");
btif_update_remote_version_property(&bd_addr);
invoke_acl_state_changed_cb(
BT_STATUS_SUCCESS, bd_addr, BT_ACL_STATE_CONNECTED,
(int)p_data->link_up.transport_link_type, HCI_SUCCESS);
break;
case BTA_DM_LINK_DOWN_EVT:
bd_addr = p_data->link_down.bd_addr;
btm_set_bond_type_dev(p_data->link_down.bd_addr,
tBTM_SEC_DEV_REC::BOND_TYPE_UNKNOWN);
btif_av_acl_disconnected(bd_addr);
invoke_acl_state_changed_cb(
BT_STATUS_SUCCESS, bd_addr, BT_ACL_STATE_DISCONNECTED,
(int)p_data->link_down.transport_link_type,
static_cast<bt_hci_error_code_t>(btm_get_acl_disc_reason_code()));
LOG_DEBUG(
"Sent BT_ACL_STATE_DISCONNECTED upward as ACL link down event "
"device:%s reason:%s",
PRIVATE_ADDRESS(bd_addr),
hci_reason_code_text(
static_cast<tHCI_REASON>(btm_get_acl_disc_reason_code()))
.c_str());
break;
case BTA_DM_BLE_KEY_EVT:
BTIF_TRACE_DEBUG("BTA_DM_BLE_KEY_EVT key_type=0x%02x ",
p_data->ble_key.key_type);
/* If this pairing is by-product of local initiated GATT client Read or
Write,
BTA would not have sent BTA_DM_BLE_SEC_REQ_EVT event and Bond state would
not
have setup properly. Setup pairing_cb and notify App about Bonding state
now*/
if (pairing_cb.state != BT_BOND_STATE_BONDING) {
BTIF_TRACE_DEBUG(
"Bond state not sent to App so far.Notify the app now");
bond_state_changed(BT_STATUS_SUCCESS, p_data->ble_key.bd_addr,
BT_BOND_STATE_BONDING);
} else if (pairing_cb.bd_addr != p_data->ble_key.bd_addr) {
BTIF_TRACE_ERROR("BD mismatch discard BLE key_type=%d ",
p_data->ble_key.key_type);
break;
}
switch (p_data->ble_key.key_type) {
case BTM_LE_KEY_PENC:
BTIF_TRACE_DEBUG("Rcv BTM_LE_KEY_PENC");
pairing_cb.ble.is_penc_key_rcvd = true;
pairing_cb.ble.penc_key = p_data->ble_key.p_key_value->penc_key;
break;
case BTM_LE_KEY_PID:
BTIF_TRACE_DEBUG("Rcv BTM_LE_KEY_PID");
pairing_cb.ble.is_pid_key_rcvd = true;
pairing_cb.ble.pid_key = p_data->ble_key.p_key_value->pid_key;
break;
case BTM_LE_KEY_PCSRK:
BTIF_TRACE_DEBUG("Rcv BTM_LE_KEY_PCSRK");
pairing_cb.ble.is_pcsrk_key_rcvd = true;
pairing_cb.ble.pcsrk_key = p_data->ble_key.p_key_value->pcsrk_key;
break;
case BTM_LE_KEY_LENC:
BTIF_TRACE_DEBUG("Rcv BTM_LE_KEY_LENC");
pairing_cb.ble.is_lenc_key_rcvd = true;
pairing_cb.ble.lenc_key = p_data->ble_key.p_key_value->lenc_key;
break;
case BTM_LE_KEY_LCSRK:
BTIF_TRACE_DEBUG("Rcv BTM_LE_KEY_LCSRK");
pairing_cb.ble.is_lcsrk_key_rcvd = true;
pairing_cb.ble.lcsrk_key = p_data->ble_key.p_key_value->lcsrk_key;
break;
case BTM_LE_KEY_LID:
BTIF_TRACE_DEBUG("Rcv BTM_LE_KEY_LID");
pairing_cb.ble.is_lidk_key_rcvd = true;
break;
default:
BTIF_TRACE_ERROR("unknown BLE key type (0x%02x)",
p_data->ble_key.key_type);
break;
}
break;
case BTA_DM_BLE_CONSENT_REQ_EVT:
BTIF_TRACE_DEBUG("BTA_DM_BLE_CONSENT_REQ_EVT. ");
btif_dm_ble_sec_req_evt(&p_data->ble_req, true);
break;
case BTA_DM_BLE_SEC_REQ_EVT:
BTIF_TRACE_DEBUG("BTA_DM_BLE_SEC_REQ_EVT. ");
btif_dm_ble_sec_req_evt(&p_data->ble_req, false);
break;
case BTA_DM_BLE_PASSKEY_NOTIF_EVT:
BTIF_TRACE_DEBUG("BTA_DM_BLE_PASSKEY_NOTIF_EVT. ");
btif_dm_ble_key_notif_evt(&p_data->key_notif);
break;
case BTA_DM_BLE_PASSKEY_REQ_EVT:
BTIF_TRACE_DEBUG("BTA_DM_BLE_PASSKEY_REQ_EVT. ");
btif_dm_ble_passkey_req_evt(&p_data->pin_req);
break;
case BTA_DM_BLE_NC_REQ_EVT:
BTIF_TRACE_DEBUG("BTA_DM_BLE_PASSKEY_REQ_EVT. ");
btif_dm_ble_key_nc_req_evt(&p_data->key_notif);
break;
case BTA_DM_BLE_OOB_REQ_EVT:
BTIF_TRACE_DEBUG("BTA_DM_BLE_OOB_REQ_EVT. ");
btif_dm_ble_oob_req_evt(&p_data->rmt_oob);
break;
case BTA_DM_BLE_SC_OOB_REQ_EVT:
BTIF_TRACE_DEBUG("BTA_DM_BLE_SC_OOB_REQ_EVT. ");
btif_dm_ble_sc_oob_req_evt(&p_data->rmt_oob);
break;
case BTA_DM_BLE_SC_CR_LOC_OOB_EVT:
BTIF_TRACE_DEBUG("BTA_DM_BLE_SC_CR_LOC_OOB_EVT");
btif_dm_proc_loc_oob(BT_TRANSPORT_LE, true,
p_data->local_oob_data.local_oob_c,
p_data->local_oob_data.local_oob_r);
break;
case BTA_DM_BLE_LOCAL_IR_EVT:
BTIF_TRACE_DEBUG("BTA_DM_BLE_LOCAL_IR_EVT. ");
ble_local_key_cb.is_id_keys_rcvd = true;
ble_local_key_cb.id_keys.irk = p_data->ble_id_keys.irk;
ble_local_key_cb.id_keys.ir = p_data->ble_id_keys.ir;
ble_local_key_cb.id_keys.dhk = p_data->ble_id_keys.dhk;
btif_storage_add_ble_local_key(ble_local_key_cb.id_keys.irk,
BTIF_DM_LE_LOCAL_KEY_IRK);
btif_storage_add_ble_local_key(ble_local_key_cb.id_keys.ir,
BTIF_DM_LE_LOCAL_KEY_IR);
btif_storage_add_ble_local_key(ble_local_key_cb.id_keys.dhk,
BTIF_DM_LE_LOCAL_KEY_DHK);
break;
case BTA_DM_BLE_LOCAL_ER_EVT:
BTIF_TRACE_DEBUG("BTA_DM_BLE_LOCAL_ER_EVT. ");
ble_local_key_cb.is_er_rcvd = true;
ble_local_key_cb.er = p_data->ble_er;
btif_storage_add_ble_local_key(ble_local_key_cb.er,
BTIF_DM_LE_LOCAL_KEY_ER);
break;
case BTA_DM_BLE_AUTH_CMPL_EVT:
BTIF_TRACE_DEBUG("BTA_DM_BLE_AUTH_CMPL_EVT. ");
btif_dm_ble_auth_cmpl_evt(&p_data->auth_cmpl);
break;
case BTA_DM_LE_FEATURES_READ:
btif_get_adapter_property(BT_PROPERTY_LOCAL_LE_FEATURES);
break;
/* add case for HANDLE_KEY_MISSING */
case BTA_DM_REPORT_BONDING_EVT:
LOG_WARN("Received encryption failed: Report bonding firstly.");
bd_addr = p_data->delete_key_RC_to_unpair.bd_addr;
invoke_bond_state_changed_cb(BT_STATUS_SUCCESS, bd_addr, BT_BOND_STATE_BONDING,
pairing_cb.fail_reason);
btif_dm_remove_bond(bd_addr);
break;
default:
BTIF_TRACE_WARNING("%s: unhandled event (%d)", __func__, event);
break;
}
}
btif_dm btif_dm_pin_req_evt
调用btif_dm的btif_dm_pin_req_evt方法:
//packages/modules/Bluetooth/system/btif/src/btif_dm.cc
static void btif_dm_pin_req_evt(tBTA_DM_PIN_REQ* p_pin_req) {
bt_bdname_t bd_name;
uint32_t cod;
bt_pin_code_t pin_code;
int dev_type;
/* Remote properties update */
if (BTM_GetPeerDeviceTypeFromFeatures(p_pin_req->bd_addr) ==
BT_DEVICE_TYPE_DUMO) {
dev_type = BT_DEVICE_TYPE_DUMO;
} else if (!btif_get_device_type(p_pin_req->bd_addr, &dev_type)) {
// Failed to get device type, defaulting to BR/EDR.
dev_type = BT_DEVICE_TYPE_BREDR;
}
btif_update_remote_properties(p_pin_req->bd_addr, p_pin_req->bd_name,
p_pin_req->dev_class,
(tBT_DEVICE_TYPE)dev_type);
const RawAddress& bd_addr = p_pin_req->bd_addr;
memcpy(bd_name.name, p_pin_req->bd_name, BD_NAME_LEN);
bd_name.name[BD_NAME_LEN] = '\0';
if (pairing_cb.state == BT_BOND_STATE_BONDING &&
bd_addr != pairing_cb.bd_addr) {
BTIF_TRACE_WARNING("%s(): already in bonding state, reject request",
__FUNCTION__);
return;
}
bond_state_changed(BT_STATUS_SUCCESS, bd_addr, BT_BOND_STATE_BONDING);
cod = devclass2uint(p_pin_req->dev_class);
if (cod == 0) {
BTIF_TRACE_DEBUG("%s cod is 0, set as unclassified", __func__);
cod = COD_UNCLASSIFIED;
}
/* check for auto pair possiblity only if bond was initiated by local device
*/
if (pairing_cb.is_local_initiated && !p_pin_req->min_16_digit) {
if (check_cod(&bd_addr, COD_AV_HEADSETS) ||
check_cod(&bd_addr, COD_AV_HEADPHONES) ||
check_cod(&bd_addr, COD_AV_PORTABLE_AUDIO) ||
check_cod(&bd_addr, COD_AV_HIFI_AUDIO) ||
check_cod(&bd_addr, COD_HID_POINTING)) {
/* Check if this device can be auto paired */
if (!interop_match_addr(INTEROP_DISABLE_AUTO_PAIRING, &bd_addr) &&
!interop_match_name(INTEROP_DISABLE_AUTO_PAIRING,
(const char*)bd_name.name) &&
(pairing_cb.autopair_attempts == 0)) {
BTIF_TRACE_DEBUG("%s() Attempting auto pair", __func__);
pin_code.pin[0] = 0x30;
pin_code.pin[1] = 0x30;
pin_code.pin[2] = 0x30;
pin_code.pin[3] = 0x30;
pairing_cb.autopair_attempts++;
BTA_DmPinReply(bd_addr, true, 4, pin_code.pin);
return;
}
} else if (check_cod(&bd_addr, COD_HID_KEYBOARD) ||
check_cod(&bd_addr, COD_HID_COMBO)) {
if ((interop_match_addr(INTEROP_KEYBOARD_REQUIRES_FIXED_PIN, &bd_addr) ==
true) &&
(pairing_cb.autopair_attempts == 0)) {
BTIF_TRACE_DEBUG("%s() Attempting auto pair", __func__);
pin_code.pin[0] = 0x30;
pin_code.pin[1] = 0x30;
pin_code.pin[2] = 0x30;
pin_code.pin[3] = 0x30;
pairing_cb.autopair_attempts++;
BTA_DmPinReply(bd_addr, true, 4, pin_code.pin);
return;
}
}
}
invoke_pin_request_cb(bd_addr, bd_name, cod, p_pin_req->min_16_digit);
}
调用invoke_pin_request_cb方法:
//packages/modules/Bluetooth/system/btif/src/bluetooth.cc
void invoke_pin_request_cb(RawAddress bd_addr, bt_bdname_t bd_name,
uint32_t cod, bool min_16_digit) {
do_in_jni_thread(FROM_HERE, base::BindOnce(
[](RawAddress bd_addr, bt_bdname_t bd_name,
uint32_t cod, bool min_16_digit) {
HAL_CBACK(bt_hal_cbacks, pin_request_cb,
&bd_addr, &bd_name, cod,
min_16_digit);
},
bd_addr, bd_name, cod, min_16_digit));
}
调用pin_request_cb,pin_request_cb是一个函数指针,包含在bt_callbacks_t的结构体里面,类型为pin_request_callback:
//packsges/modules/Bluetooth/android/app/jni/com_android_bluetooth_btservice_dapterService.cpp
//Bluetooth Legacy PinKey Request callback
static void pin_request_callback(RawAddress* bd_addr, bt_bdname_t* bdname,
uint32_t cod, bool min_16_digits) {
if (!bd_addr) {
ALOGE("Address is null in %s", __func__);
return;
}
CallbackEnv sCallbackEnv(__func__);
if (!sCallbackEnv.valid()) return;
ScopedLocalRef<jbyteArray> addr(
sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(RawAddress)));
if (!addr.get()) {
ALOGE("Error while allocating in: %s", __func__);
return;
}
sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress),
(jbyte*)bd_addr);
ScopedLocalRef<jbyteArray> devname(
sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(bt_bdname_t)));
if (!devname.get()) {
ALOGE("Error while allocating in: %s", __func__);
return;
}
sCallbackEnv->SetByteArrayRegion(devname.get(), 0, sizeof(bt_bdname_t),
(jbyte*)bdname);
sCallbackEnv->CallVoidMethod(sJniCallbacksObj, method_pinRequestCallback,
addr.get(), devname.get(), cod, min_16_digits);
}
调用method_pinRequestCallback方法,在classInitNative中定义如下:
//packsges/modules/Bluetooth/android/app/jni/com_android_bluetooth_btservice_dapterService.cpp
static void classInitNative(JNIEnv* env, jclass clazz) {
method_pinRequestCallback =
env->GetMethodID(jniCallbackClass, "pinRequestCallback", "([B[BIZ)V");
}
调用JniCallbacks的pinRequestCallbackfang:
//packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/JniCallbacks.java
final class JniCallbacks {
void pinRequestCallback(byte[] address, byte[] name, int cod, boolean min16Digits) {
mBondStateMachine.pinRequestCallback(address, name, cod, min16Digits);
}
}
BondStateMachine pinRequestCallback
调用BondStateMachine的pinRequestCallback方法:
//packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/BondStateMachine.java
final class BondStateMachine extends StateMachine {
void pinRequestCallback(byte[] address, byte[] name, int cod, boolean min16Digits) {
//TODO(BT): Get wakelock and update name and cod
BluetoothDevice bdDevice = mRemoteDevices.getDevice(address);
if (bdDevice == null) {
mRemoteDevices.addDeviceProperties(address);
bdDevice = Objects.requireNonNull(mRemoteDevices.getDevice(address));
}
BluetoothStatsLog.write(BluetoothStatsLog.BLUETOOTH_BOND_STATE_CHANGED,
mAdapterService.obfuscateAddress(bdDevice), 0, bdDevice.getType(),
BluetoothDevice.BOND_BONDING,
BluetoothProtoEnums.BOND_SUB_STATE_LOCAL_PIN_REQUESTED, 0);
infoLog("pinRequestCallback: " + bdDevice.getAddress()
+ " name:" + Utils.getName(bdDevice) + " cod:" + new BluetoothClass(cod));
Message msg = obtainMessage(PIN_REQUEST);
msg.obj = bdDevice;
msg.arg2 = min16Digits ? 1 : 0; // Use arg2 to pass the min16Digit boolean
sendMessage(msg); //发送PIN_REQUEST消息
}
}
调用sendMessage方法发送PIN_REQUEST消息,发送的消息在BondStateMachine的内部类PendingCommandState的processMessage方法中处理:
//packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/BondStateMachine.java
final class BondStateMachine extends StateMachine {
private class PendingCommandState extends State {
private final ArrayList<BluetoothDevice> mDevices = new ArrayList<BluetoothDevice>();
@Override
public void enter() {
infoLog("Entering PendingCommandState State");
}
@Override
public synchronized boolean processMessage(Message msg) {
BluetoothDevice dev = (BluetoothDevice) msg.obj;
DeviceProperties devProp = mRemoteDevices.getDeviceProperties(dev);
boolean result = false;
if ((mDevices.contains(dev) || mPendingBondedDevices.contains(dev))
&& msg.what != CANCEL_BOND && msg.what != BONDING_STATE_CHANGE
&& msg.what != SSP_REQUEST && msg.what != PIN_REQUEST) {
deferMessage(msg);
return true;
}
switch (msg.what) {
case CREATE_BOND:
OobData p192Data = (msg.getData() != null)
? msg.getData().getParcelable(OOBDATAP192) : null;
OobData p256Data = (msg.getData() != null)
? msg.getData().getParcelable(OOBDATAP256) : null;
result = createBond(dev, msg.arg1, p192Data, p256Data, false);
break;
case REMOVE_BOND:
result = removeBond(dev, false);
break;
case CANCEL_BOND:
result = cancelBond(dev);
break;
case BONDING_STATE_CHANGE:
int newState = msg.arg1;
int reason = getUnbondReasonFromHALCode(msg.arg2);
// Bond is explicitly removed if we are in pending command state
if (newState == BluetoothDevice.BOND_NONE
&& reason == BluetoothDevice.BOND_SUCCESS) {
reason = BluetoothDevice.UNBOND_REASON_REMOVED;
}
sendIntent(dev, newState, reason, false);
if (newState != BluetoothDevice.BOND_BONDING) {
// This is either none/bonded, remove and transition, and also set
// result=false to avoid adding the device to mDevices.
mDevices.remove(dev);
result = false;
if (mDevices.isEmpty()) {
transitionTo(mStableState);
}
if (newState == BluetoothDevice.BOND_NONE) {
mAdapterService.setPhonebookAccessPermission(dev,
BluetoothDevice.ACCESS_UNKNOWN);
mAdapterService.setMessageAccessPermission(dev,
BluetoothDevice.ACCESS_UNKNOWN);
mAdapterService.setSimAccessPermission(dev,
BluetoothDevice.ACCESS_UNKNOWN);
// Set the profile Priorities to undefined
clearProfilePriority(dev);
}
} else if (!mDevices.contains(dev)) {
result = true;
}
break;
case SSP_REQUEST:
int passkey = msg.arg1;
int variant = msg.arg2;
sendDisplayPinIntent(devProp.getAddress(), passkey, variant);
break;
case PIN_REQUEST:
BluetoothClass btClass = dev.getBluetoothClass();
int btDeviceClass = btClass.getDeviceClass();
if (btDeviceClass == BluetoothClass.Device.PERIPHERAL_KEYBOARD || btDeviceClass
== BluetoothClass.Device.PERIPHERAL_KEYBOARD_POINTING) {
// Its a keyboard. Follow the HID spec recommendation of creating the
// passkey and displaying it to the user. If the keyboard doesn't follow
// the spec recommendation, check if the keyboard has a fixed PIN zero
// and pair.
//TODO: Maintain list of devices that have fixed pin
// Generate a variable 6-digit PIN in range of 100000-999999
// This is not truly random but good enough.
int pin = 100000 + (int) Math.floor((Math.random() * (999999 - 100000)));
sendDisplayPinIntent(devProp.getAddress(), pin,
BluetoothDevice.PAIRING_VARIANT_DISPLAY_PIN);
break;
}
if (msg.arg2 == 1) { // Minimum 16 digit pin required here
sendDisplayPinIntent(devProp.getAddress(), 0,
BluetoothDevice.PAIRING_VARIANT_PIN_16_DIGITS);
} else {
// In PIN_REQUEST, there is no passkey to display.So do not send the
// EXTRA_PAIRING_KEY type in the intent( 0 in SendDisplayPinIntent() )
sendDisplayPinIntent(devProp.getAddress(), 0,
BluetoothDevice.PAIRING_VARIANT_PIN);
}
break;
default:
Log.e(TAG, "Received unhandled event:" + msg.what);
return false;
}
if (result) {
mDevices.add(dev);
}
return true;
}
}
}
BondStateMachine sendDisplayPinIntent
调用BondStateMachine的sendDisplayPinIntent方法:
//packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/BondStateMachine.java
final class BondStateMachine extends StateMachine {
private void sendDisplayPinIntent(byte[] address, int pin, int variant) {
Intent intent = new Intent(BluetoothDevice.ACTION_PAIRING_REQUEST); //创建配对码广播
intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mRemoteDevices.getDevice(address));
if (pin != 0) {
intent.putExtra(BluetoothDevice.EXTRA_PAIRING_KEY, pin);
}
intent.putExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT, variant);
intent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
// Workaround for Android Auto until pre-accepting pairing requests is added.
intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
mAdapterService.sendOrderedBroadcast(intent, BLUETOOTH_CONNECT, /*权限字符串,只有具有该权限的接收器才能接收到广播*/
Utils.getTempAllowlistBroadcastOptions(), null/* resultReceiver */,
null/* scheduler */, Activity.RESULT_OK/* initialCode */, null/* initialData */,
null/* initialExtras */); //发送广播
}
}