Android13 ACTION_PAIRING_REQUEST广播发送流程

当蓝牙配对后会发送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 */); //发送广播
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值