Android Bluetooth scan process

Keywords: Android bluetooth

Android Bluetooth framework

1, scan in Settings interface

Enter the android setting interface and open Bluetooth, and the scanning will start automatically.
Let's start with the android Bluetooth setting interface:

Bluetooth switch button
BluetoothSettings.java (packages\apps\settings\src\com\android\settings\bluetooth)

public final class BluetoothSettings extends DeviceListPreferenceFragment implements Indexable 
	private BluetoothEnabler mBluetoothEnabler;
	public void onActivityCreated(Bundle savedInstanceState)
		mBluetoothEnabler = new BluetoothEnabler(activity, mSwitchBar);
        mBluetoothEnabler.setupSwitchBar();
        	mSwitchBar.show(); // Display Bluetooth switch button

    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

Turn on Bluetooth
BluetoothEnabler.java (packages\apps\settings\src\com\android\settings\bluetooth)

onSwitchChanged()
     mLocalAdapter.setBluetoothEnabled(isChecked);

    
  • 1
  • 2

Please refer to my previous article for the process of opening Bluetooth Android Bluetooth enable process , not described here. When Bluetooth is successfully opened, it will be recalled from the protocol stack, call onbluetooth statechanged, and finally call startScanning.

    public void onBluetoothStateChanged(int bluetoothState) {
        super.onBluetoothStateChanged(bluetoothState);
        updateContent(bluetoothState);
    }
<span class="token keyword">private</span> <span class="token keyword">void</span> <span class="token function">updateContent</span><span class="token punctuation">(</span><span class="token keyword">int</span> bluetoothState<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
    <span class="token keyword">final</span> PreferenceScreen preferenceScreen <span class="token operator">=</span> <span class="token function">getPreferenceScreen</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">int</span> messageId <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>

    <span class="token keyword">switch</span> <span class="token punctuation">(</span>bluetoothState<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
        <span class="token keyword">case</span> BluetoothAdapter<span class="token punctuation">.</span>STATE_ON<span class="token operator">:</span>
            preferenceScreen<span class="token punctuation">.</span><span class="token function">removeAll</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            preferenceScreen<span class="token punctuation">.</span><span class="token function">setOrderingAsAdded</span><span class="token punctuation">(</span><span class="token boolean">true</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            mDevicePreferenceMap<span class="token punctuation">.</span><span class="token function">clear</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            mPairedDevicesCategory<span class="token punctuation">.</span><span class="token function">removeAll</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
			mAvailableDevicesCategory<span class="token punctuation">.</span><span class="token function">removeAll</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>mInitialScanStarted<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
                <span class="token function">startScanning</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//Start scan</span>
                	mLocalAdapter<span class="token punctuation">.</span><span class="token function">startScanning</span><span class="token punctuation">(</span><span class="token boolean">true</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token punctuation">}</span>
	<span class="token punctuation">}</span>

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

LocalBluetoothAdapter.java (packages\apps\settings\src\com\android\settings\bluetooth)

    void startScanning(boolean force) {
        if (!mAdapter.isDiscovering()) {
            if (mAdapter.startDiscovery()) {
                mLastScan = System.currentTimeMillis();
            }
        }
    }

 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

BluetoothAdapter.java (frameworks\base\core\java\android\bluetooth)

    public boolean startDiscovery() {
        if (getState() != STATE_ON) return false;
        try {
            synchronized(mManagerCallback) {
                if (mService != null) return mService.startDiscovery();
            }
        } catch (RemoteException e) {Log.e(TAG, "", e);}
        return false;
    }

 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

View the definition of mService:

    private IBluetooth mService;

 
  • 1

mService calls startDiscovery through binder.
AdapterService.java(packages\apps\bluetooth\src\com\android\bluetooth\btservice)

public class AdapterService extends Service {
    boolean startDiscovery() {
       enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
                                      "Need BLUETOOTH ADMIN permission");
       return startDiscoveryNative();
   }

private static class AdapterServiceBinder extends IBluetooth.Stub {
public boolean startDiscovery() {
AdapterService service = getService();
if (service == null) return false;
return service.startDiscovery();
}
}
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

Check the definition of startdiscoverynational. You can see that it is a native method:

private native boolean startDiscoveryNative();

 
  • 1

com_android_bluetooth_btservice_AdapterService.cpp (packages\apps\bluetooth\jni)

static jboolean startDiscoveryNative(JNIEnv* env, jobject obj) {
   int ret = sBluetoothInterface->start_discovery();
}

 
  • 1
  • 2
  • 3

View definition

static const bt_interface_t *sBluetoothInterface = NULL;

 
  • 1

Find the assignment of sBluetoothInterface and find that it loads a bluetooth.defalt.so module:

#define BT_HARDWARE_MODULE_ID "bluetooth"
#define BT_STACK_MODULE_ID "bluetooth"
#define BT_STACK_TEST_MODULE_ID "bluetooth_test"
static void classInitNative(JNIEnv* env, jclass clazz)
{
   hw_module_t* module;
   const char *id = (strcmp(value, "1")? BT_STACK_MODULE_ID :  
   		BT_STACK_TEST_MODULE_ID);
   // Load btStack module bluetooth.defaalt.so
   err = hw_get_module(id, (hw_module_t const**)&module);
   if (err == 0) {
       hw_device_t* abstraction;
       err = module->methods->open(module, id, &abstraction);
       if (err == 0) {
   		//Finally, it is converted to btStack structure
           bluetooth_module_t* btStack = (bluetooth_module_t *)abstraction;
           // sBluetoothInterface assignment
           sBluetoothInterface = btStack->get_bluetooth_interface();
       } else {
          ALOGE("Error while opening Bluetooth library");
       }
   } else {
       ALOGE("No Bluetooth Library found");
   } 
}

 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

View hw_get_module definition:
Hardware.c (hardware\libhardware)

 /** Base path of the hal modules */
#if defined(__LP64__)
#define HAL_LIBRARY_PATH1 "/system/lib64/hw"
#define HAL_LIBRARY_PATH2 "/vendor/lib64/hw"
#else
#define HAL_LIBRARY_PATH1 "/system/lib/hw"
#define HAL_LIBRARY_PATH2 "/vendor/lib/hw"
#endif

/*

  • Check if a HAL with given name and subname exists, if so return 0, otherwise

  • otherwise return negative. On success path will contain the path to the HAL.
    /
    static int hw_module_exists(char path, size_t path_len, const char name,
    const char subname)
    {
    snprintf(path, path_len, "%s/%s.%s.so",
    HAL_LIBRARY_PATH2, name, subname);
    if (access(path, R_OK) == 0)
    return 0;

    snprintf(path, path_len, "%s/%s.%s.so",
    HAL_LIBRARY_PATH1, name, subname);
    if (access(path, R_OK) == 0)
    return 0;

    return -ENOENT;
    }

int hw_get_module(const char id, const struct hw_module_t module)
hw_get_module_by_class(id, NULL, module);
int hw_get_module_by_class(const char class_id, const char inst,
const struct hw_module_t *module)
{
char path[PATH_MAX];
char name[PATH_MAX];

strlcpy(name, class_id, PATH_MAX);

/* Nothing found, try the default */
//Find the module bluetooth.default.so
if (hw_module_exists(path, sizeof(path), name, "default") == 0) {
goto found;
}

found:
return load(class_id, path, module);
void handle;
struct hw_module_t hmi;
handle = dlopen(path, RTLD_NOW);
/* Get the address of the struct hal_module_info. /
const char sym = HAL_MODULE_INFO_SYM_AS_STR;
hmi = (struct hw_module_t *)dlsym(handle, sym);
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54

Bluetooth.c (external\bluetooth\bluedroid\btif\src)
We know that the BlueDroid protocol stack code compilation will generate the bluetooth.defalt.so module, and the code is in the external\bluetooth\bluedroid directory.

static const bt_interface_t bluetoothInterface
   start_discovery,
   	btif_dm_start_discovery();

 
  • 1
  • 2
  • 3

Btif_dm.c (external\bluetooth\bluedroid\btif\src)

  bt_status_t btif_dm_start_discovery(void)
   	inq_params.mode = BTA_DM_GENERAL_INQUIRY;
   	inq_params.duration = BTIF_DM_DEFAULT_INQ_MAX_DURATION; // Scanning time 10*1.28 s
   	inq_params.max_resps = BTIF_DM_DEFAULT_INQ_MAX_RESULTS; 
   	inq_params.report_dup = TRUE;
   	inq_params.filter_type = BTA_DM_INQ_CLR;
   	BTA_DmSearch(&inq_params, services, bte_search_devices_evt);
   		p_msg->hdr.event = BTA_DM_API_SEARCH_EVT;
   		memcpy(&p_msg->inq_params, p_dm_inq, sizeof(tBTA_DM_INQ));
   		p_msg->services = services;
   		p_msg->p_cback = p_cback;
   		p_msg->rs_res  = BTA_DM_RS_NONE;
   		bta_sys_sendmsg(p_msg);

 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

btif_dm_start_discovery calls BTA_DmSearch, send a BTA_DM_API_SEARCH_EVT messages will be sent to BTU in the end_ Task processing.

Bta_sys_main.c (external\bluetooth\bluedroid\bta\sys)

void bta_sys_sendmsg(void *p_msg)
{
   GKI_send_msg(bta_sys_cb.task_id, p_bta_sys_cfg->mbox, p_msg);
   	 GKI_send_event(task_id, (UINT16)EVENT_MASK(mbox));
}

 
  • 1
  • 2
  • 3
  • 4
  • 5

View BTA_ sys_ cb.task_ Assignment of ID:

BTA_API void bta_sys_init(void)
    bta_sys_cb.task_id = GKI_get_taskid();

 
  • 1
  • 2

bta_sys_init in BTU_ Called in task, so task_id equals BTU_ The task id of the task. The message is in BTU_ Receive processing in task.

View p_ bta_ sys_ Assignment of CFG - > Mbox:

// gki.h (external\bluetooth\bluedroid\gki\common)
/************************************************************************
** Mailbox definitions. Each task has 4 mailboxes that are used to
** send buffers to the task.
*/
#define TASK_MBOX_0    0
#define TASK_MBOX_1    1
#define TASK_MBOX_2    2
#define TASK_MBOX_3    3

#define NUM_TASK_MBOX 4

/************************************************************************
** Event definitions.
**
** There are 4 reserved events used to signal messages rcvd in task mailboxes.
** There are 4 reserved events used to signal timeout events.
** There are 8 general purpose events available for applications.
*/
#define MAX_EVENTS 16

#define TASK_MBOX_0_EVT_MASK 0x0001
#define TASK_MBOX_1_EVT_MASK 0x0002
#define TASK_MBOX_2_EVT_MASK 0x0004
#define TASK_MBOX_3_EVT_MASK 0x0008

//bta_sys.h (external\bluetooth\bluedroid\bta\sys)
/* system manager configuration structure /
typedef struct
{
UINT16 mbox_evt; / GKI mailbox event /
UINT8 mbox; / GKI mailbox id /
UINT8 timer; / GKI timer id /
UINT8 trace_level; / initial trace level */
} tBTA_SYS_CFG;

// bta_sys_cfg.c (external\bluetooth\bluedroid\bta\sys)
/* GKI task mailbox event for BTA. */
#define BTA_MBOX_EVT TASK_MBOX_2_EVT_MASK

/* GKI task mailbox for BTA. */
#define BTA_MBOX TASK_MBOX_2

const tBTA_SYS_CFG bta_sys_cfg =
{
BTA_MBOX_EVT, /* GKI mailbox event /
BTA_MBOX, / GKI mailbox id /
BTA_TIMER, / GKI timer id /
APPL_INITIAL_TRACE_LEVEL / initial trace level */
};

tBTA_SYS_CFG p_bta_sys_cfg = (tBTA_SYS_CFG )&bta_sys_cfg;

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52

So p_ bta_ sys_ CFG - > Mbox equals TASK_MBOX_2, EVENT_MASK(mbox) is equal to TASK_MBOX_2_EVT_MASK.

btu_task.c (external\bluetooth\bluedroid\stack\btu)

/*******************************************************************************
**
** Function         btu_task
**
** Description      This is the main task of the Bluetooth Upper Layers unit.
**                  It sits in a loop waiting for messages, and dispatches them
**                  to the appropiate handlers.
**
** Returns          should never return
**
*******************************************************************************/
BTU_API UINT32 btu_task (UINT32 param)
{
    UINT16           event;
    BT_HDR          *p_msg;
    UINT8            i;
    UINT16           mask;
    BOOLEAN          handled;
<span class="token comment">/* Initialize the mandatory core stack control blocks
   (BTU, BTM, L2CAP, and SDP)
 */</span>
<span class="token function">btu_init_core</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">/* Initialize any optional stack components */</span>
<span class="token function">BTE_InitStack</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

#if (defined(BTU_BTA_INCLUDED) && BTU_BTA_INCLUDED == TRUE)
bta_sys_init(); // bta init
#endif

<span class="token comment">/* Send a startup evt message to BTIF_TASK to kickstart the init procedure */</span>
<span class="token function">GKI_send_event</span><span class="token punctuation">(</span>BTIF_TASK<span class="token punctuation">,</span> BT_EVT_TRIGGER_STACK_INIT<span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">/* Wait for, and process, events */</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token punctuation">;</span><span class="token punctuation">;</span><span class="token punctuation">)</span>
<span class="token punctuation">{<!-- --></span>
    event <span class="token operator">=</span> GKI_wait <span class="token punctuation">(</span><span class="token number">0xFFFF</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>event <span class="token operator">&amp;</span> TASK_MBOX_0_EVT_MASK<span class="token punctuation">)</span>
    <span class="token punctuation">{<!-- --></span>
        <span class="token comment">/* Process all messages in the queue */</span>
    <span class="token punctuation">}</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>event <span class="token operator">&amp;</span> TIMER_0_EVT_MASK<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>

    <span class="token punctuation">}</span>

#if (defined(BTU_BTA_INCLUDED) && BTU_BTA_INCLUDED == TRUE)
if (event & TASK_MBOX_2_EVT_MASK)
{
while ((p_msg = (BT_HDR ) GKI_read_mbox(TASK_MBOX_2)) != NULL)
{
bta_sys_event(p_msg);
UINT8 id;
BOOLEAN freebuf = TRUE;
//event equals BTA_DM_API_SEARCH_EVT, id equals BTA_ID_DM_SEARCH, corresponding cb function BTA_ dm_ search_ Reg (registered in btif_task - > bta_enablebluetooth)
id = (UINT8) (p_msg->event >> 8);
//Call BTA_ dm_ search_ BTA of reg_ dm_ search_ sm_ Execute function
freebuf = (bta_sys_cb.reg[id]->evt_hdlr)(p_msg);

    <span class="token keyword">if</span> <span class="token punctuation">(</span>event <span class="token operator">&amp;</span> TIMER_1_EVT_MASK<span class="token punctuation">)</span>
    <span class="token punctuation">{<!-- --></span>
        <span class="token function">bta_sys_timer_update</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

#endif
if (event & TIMER_3_EVT_MASK) {

    <span class="token punctuation">}</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>event <span class="token operator">&amp;</span> <span class="token function">EVENT_MASK</span><span class="token punctuation">(</span>APPL_EVT_7<span class="token punctuation">)</span><span class="token punctuation">)</span>
        <span class="token keyword">break</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token keyword">return</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74

bta_dm_main.c (external\bluetooth\bluedroid\bta\dm)
bta_dm_search_sm_execute in BTA_ dm_ search_ Take BTA from the action function list_ DM_ API_ Search function bta_dm_search_start and call.

/* action function list */
const tBTA_DM_ACTION bta_dm_search_action[] =
{

bta_dm_search_start, /* 0 BTA_DM_API_SEARCH /
bta_dm_search_cancel, / 1 BTA_DM_API_SEARCH_CANCEL /
bta_dm_discover, / 2 BTA_DM_API_DISCOVER /
bta_dm_inq_cmpl, / 3 BTA_DM_INQUIRY_CMPL /
bta_dm_rmt_name, / 4 BTA_DM_REMT_NAME /
bta_dm_sdp_result, / 5 BTA_DM_SDP_RESULT /
bta_dm_search_cmpl, / 6 BTA_DM_SEARCH_CMPL /
bta_dm_free_sdp_db, / 7 BTA_DM_FREE_SDP_DB /
bta_dm_disc_result, / 8 BTA_DM_DISC_RESULT /
bta_dm_search_result, / 9 BTA_DM_SEARCH_RESULT /
bta_dm_queue_search, / 10 BTA_DM_QUEUE_SEARCH /
bta_dm_queue_disc, / 11 BTA_DM_QUEUE_DISC /
bta_dm_search_clear_queue, / 12 BTA_DM_SEARCH_CLEAR_QUEUE /
bta_dm_search_cancel_cmpl, / 13 BTA_DM_SEARCH_CANCEL_CMPL /
bta_dm_search_cancel_notify, / 14 BTA_DM_SEARCH_CANCEL_NOTIFY /
bta_dm_search_cancel_transac_cmpl, / 15 BTA_DM_SEARCH_CANCEL_TRANSAC_CMPL /
bta_dm_disc_rmt_name, / 16 BTA_DM_DISC_RMT_NAME /
bta_dm_di_disc / 17 BTA_DM_API_DI_DISCOVER */
#if BLE_INCLUDED == TRUE
,bta_dm_close_gatt_conn
#endif
};

BOOLEAN bta_dm_search_sm_execute(BT_HDR *p_msg)
{
tBTA_DM_ST_TBL state_table;
UINT8 action;
int i;

<span class="token comment">/* look up the state table for the current state */</span>
state_table <span class="token operator">=</span> bta_dm_search_st_tbl<span class="token punctuation">[</span>bta_dm_search_cb<span class="token punctuation">.</span>state<span class="token punctuation">]</span><span class="token punctuation">;</span>
bta_dm_search_cb<span class="token punctuation">.</span>state <span class="token operator">=</span> state_table<span class="token punctuation">[</span>p_msg<span class="token operator">-</span><span class="token operator">&gt;</span>event <span class="token operator">&amp;</span> <span class="token number">0x00ff</span><span class="token punctuation">]</span><span class="token punctuation">[</span>BTA_DM_SEARCH_NEXT_STATE<span class="token punctuation">]</span><span class="token punctuation">;</span>

<span class="token comment">/* execute action functions */</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span>i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator">&lt;</span> BTA_DM_SEARCH_ACTIONS<span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span>
<span class="token punctuation">{<!-- --></span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token punctuation">(</span>action <span class="token operator">=</span> state_table<span class="token punctuation">[</span>p_msg<span class="token operator">-</span><span class="token operator">&gt;</span>event <span class="token operator">&amp;</span> <span class="token number">0x00ff</span><span class="token punctuation">]</span><span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token operator">!=</span> BTA_DM_SEARCH_IGNORE<span class="token punctuation">)</span>
    <span class="token punctuation">{<!-- --></span>
        <span class="token punctuation">(</span><span class="token operator">*</span>bta_dm_search_action<span class="token punctuation">[</span>action<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">(</span> <span class="token punctuation">(</span>tBTA_DM_MSG<span class="token operator">*</span><span class="token punctuation">)</span> p_msg<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    <span class="token keyword">else</span>
    <span class="token punctuation">{<!-- --></span>
        <span class="token keyword">break</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token keyword">return</span> TRUE<span class="token punctuation">;</span>

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51

Bta_dm_act.c (external\bluetooth\bluedroid\bta\dm)

void bta_dm_search_start (tBTA_DM_MSG *p_data)
{
    result.status = BTM_StartInquiry(   (tBTM_INQ_PARMS*)&p_data->search.inq_params,
                        bta_dm_inq_results_cb,
                        (tBTM_CMPL_CB*) bta_dm_inq_cmpl_cb);
}

 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

Btm_inq.c (external\bluetooth\bluedroid\stack\btm)
BTM_ The query process of the startinquiry function includes the query of BLE and BR/EDR modes. We only focus on the BLE mode here. p_ inq->p_ inq_ results_ CB is the scan callback pointing to bta_dm_inq_results_cb, scan BTA after broadcast_ dm_ inq_ results_ CB will be called.

tBTM_STATUS BTM_StartInquiry (tBTM_INQ_PARMS *p_inqparms, tBTM_INQ_RESULTS_CB *p_results_cb, tBTM_CMPL_CB *p_cmpl_cb)
{
    /* Save the inquiry parameters to be used upon the completion of setting/clearing the inquiry filter */
    p_inq->inqparms = *p_inqparms;
<span class="token comment">/* Initialize the inquiry variables */</span>
p_inq<span class="token operator">-</span><span class="token operator">&gt;</span>state <span class="token operator">=</span> BTM_INQ_ACTIVE_STATE<span class="token punctuation">;</span>
p_inq<span class="token operator">-</span><span class="token operator">&gt;</span>p_inq_cmpl_cb <span class="token operator">=</span> p_cmpl_cb<span class="token punctuation">;</span>
p_inq<span class="token operator">-</span><span class="token operator">&gt;</span>p_inq_results_cb <span class="token operator">=</span> p_results_cb<span class="token punctuation">;</span>
p_inq<span class="token operator">-</span><span class="token operator">&gt;</span>inq_cmpl_info<span class="token punctuation">.</span>num_resp <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>         <span class="token comment">/* Clear the results counter */</span>
p_inq<span class="token operator">-</span><span class="token operator">&gt;</span>inq_active <span class="token operator">=</span> p_inqparms<span class="token operator">-</span><span class="token operator">&gt;</span>mode<span class="token punctuation">;</span>

#if BLE_INCLUDED == TRUE
/* start LE inquiry */
status = btm_ble_start_inquiry((UINT8)(p_inqparms->mode & BTM_BLE_INQUIRY_MASK), p_inqparms->duration)) != BTM_CMD_STARTED):

    <span class="token keyword">return</span> status<span class="token punctuation">;</span>

#endif
/* start br/edr inquiry */
if ((status = btm_set_inq_event_filter (p_inqparms->filter_cond_type,
&p_inqparms->filter_cond)) != BTM_CMD_STARTED)
p_inq->state = BTM_INQ_INACTIVE_STATE;
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

Btm_ble_gap.c (external\bluetooth\bluedroid\stack\btm)

tBTM_STATUS btm_ble_start_inquiry (UINT8 mode, UINT8   duration)
{
    if (!BTM_BLE_IS_SCAN_ACTIVE(p_ble_cb->scan_activity))
    {
        btm_update_scanner_filter_policy(SP_ADV_ALL);
        status = btm_ble_start_scan(BTM_BLE_DUPLICATE_DISABLE);
    }
<span class="token keyword">if</span> <span class="token punctuation">(</span>status <span class="token operator">==</span> BTM_CMD_STARTED<span class="token punctuation">)</span>
<span class="token punctuation">{<!-- --></span>
    p_inq<span class="token operator">-</span><span class="token operator">&gt;</span>inq_active <span class="token operator">|</span><span class="token operator">=</span> mode<span class="token punctuation">;</span>
    p_ble_cb<span class="token operator">-</span><span class="token operator">&gt;</span>scan_activity <span class="token operator">|</span><span class="token operator">=</span> mode<span class="token punctuation">;</span>

    <span class="token function">BTM_TRACE_DEBUG</span><span class="token punctuation">(</span><span class="token string">"btm_ble_start_inquiry inq_active = 0x%02x"</span><span class="token punctuation">,</span> p_inq<span class="token operator">-</span><span class="token operator">&gt;</span>inq_active<span class="token punctuation">)</span><span class="token punctuation">;</span>
	
    <span class="token keyword">if</span> <span class="token punctuation">(</span>duration <span class="token operator">!=</span> <span class="token number">0</span><span class="token punctuation">)</span>
    <span class="token punctuation">{<!-- --></span>
        <span class="token comment">/* Start inquiry timer */</span>
        btu_start_timer <span class="token punctuation">(</span><span class="token operator">&amp;</span>p_inq<span class="token operator">-</span><span class="token operator">&gt;</span>inq_timer_ent<span class="token punctuation">,</span> BTU_TTYPE_BLE_INQUIRY<span class="token punctuation">,</span> duration<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

btm_ble_start_inquiry mainly does three things:
1) Set scanning parameters: btm_update_scanner_filter_policy(SP_ADV_ALL)
2) Start scan: btm_ble_start_scan(BTM_BLE_DUPLICATE_DISABLE);
3) Start the scan timer. After the timer expires, the BTU_ Turn off scanning in task:
btu_start_timer (&p_inq->inq_timer_ent, BTU_TTYPE_BLE_INQUIRY, duration)

These three events are tracked as follows:

1) Set scan parameters

Btm_ble_bgconn.c (external\bluetooth\bluedroid\stack\btm)

void btm_update_scanner_filter_policy(tBTM_BLE_SFP scan_policy)
{
    p_inq->sfp = scan_policy;
    p_inq->scan_type = (p_inq->scan_type == BTM_BLE_SCAN_MODE_NONE) ? BTM_BLE_SCAN_MODE_ACTI: p_inq->scan_type;
btsnd_hcic_ble_set_scan_params <span class="token punctuation">(</span>p_inq<span class="token operator">-</span><span class="token operator">&gt;</span>scan_type<span class="token punctuation">,</span>
                                <span class="token punctuation">(</span>UINT16<span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token operator">!</span>p_inq<span class="token operator">-</span><span class="token operator">&gt;</span>scan_interval <span class="token operator">?</span> BTM_BLE_GAP_DISC_SCAN_INT <span class="token operator">:</span> p_inq<span class="token operator">-</span><span class="token operator">&gt;</span>scan_interval<span class="token punctuation">)</span><span class="token punctuation">,</span>
                                <span class="token punctuation">(</span>UINT16<span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token operator">!</span>p_inq<span class="token operator">-</span><span class="token operator">&gt;</span>scan_window <span class="token operator">?</span> BTM_BLE_GAP_DISC_SCAN_WIN <span class="token operator">:</span> p_inq<span class="token operator">-</span><span class="token operator">&gt;</span>scan_window<span class="token punctuation">)</span><span class="token punctuation">,</span>
                                 btm_cb<span class="token punctuation">.</span>ble_ctr_cb<span class="token punctuation">.</span>addr_mgnt_cb<span class="token punctuation">.</span>own_addr_type<span class="token punctuation">,</span>
                                 scan_policy<span class="token punctuation">)</span><span class="token punctuation">;</span>                             

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

Hciblecmds.c (external\bluetooth\bluedroid\stack\hcic)

BOOLEAN btsnd_hcic_ble_set_scan_params (UINT8 scan_type,
                                          UINT16 scan_int, UINT16 scan_win,
                                          UINT8 addr_type_own, UINT8 scan_filter_policy)
{
    BT_HDR *p;
    UINT8 *pp;
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token punctuation">(</span>p <span class="token operator">=</span> <span class="token function">HCI_GET_CMD_BUF</span><span class="token punctuation">(</span>HCIC_PARAM_SIZE_BLE_WRITE_SCAN_PARAM<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">==</span> <span class="token constant">NULL</span><span class="token punctuation">)</span>
    <span class="token keyword">return</span> <span class="token punctuation">(</span>FALSE<span class="token punctuation">)</span><span class="token punctuation">;</span>

pp <span class="token operator">=</span> <span class="token punctuation">(</span>UINT8 <span class="token operator">*</span><span class="token punctuation">)</span><span class="token punctuation">(</span>p <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Point to data []</span>

p<span class="token operator">-</span><span class="token operator">&gt;</span>len    <span class="token operator">=</span> HCIC_PREAMBLE_SIZE <span class="token operator">+</span> HCIC_PARAM_SIZE_BLE_WRITE_SCAN_PARAM<span class="token punctuation">;</span>
p<span class="token operator">-</span><span class="token operator">&gt;</span>offset <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>

UINT16_TO_STREAM <span class="token punctuation">(</span>pp<span class="token punctuation">,</span> HCI_BLE_WRITE_SCAN_PARAMS<span class="token punctuation">)</span><span class="token punctuation">;</span>
UINT8_TO_STREAM  <span class="token punctuation">(</span>pp<span class="token punctuation">,</span> HCIC_PARAM_SIZE_BLE_WRITE_SCAN_PARAM<span class="token punctuation">)</span><span class="token punctuation">;</span>

UINT8_TO_STREAM <span class="token punctuation">(</span>pp<span class="token punctuation">,</span> scan_type<span class="token punctuation">)</span><span class="token punctuation">;</span>
UINT16_TO_STREAM <span class="token punctuation">(</span>pp<span class="token punctuation">,</span> scan_int<span class="token punctuation">)</span><span class="token punctuation">;</span>
UINT16_TO_STREAM <span class="token punctuation">(</span>pp<span class="token punctuation">,</span> scan_win<span class="token punctuation">)</span><span class="token punctuation">;</span>
UINT8_TO_STREAM <span class="token punctuation">(</span>pp<span class="token punctuation">,</span> addr_type_own<span class="token punctuation">)</span><span class="token punctuation">;</span>
UINT8_TO_STREAM <span class="token punctuation">(</span>pp<span class="token punctuation">,</span> scan_filter_policy<span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token comment">/* Send hci command */</span>
 btu_hcif_send_cmd <span class="token punctuation">(</span>LOCAL_BR_EDR_CONTROLLER_ID<span class="token punctuation">,</span>  p<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> <span class="token punctuation">(</span>TRUE<span class="token punctuation">)</span><span class="token punctuation">;</span>

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
2) Start scan

Btm_ble_gap.c (external\bluetooth\bluedroid\stack\btm)

tBTM_STATUS btm_ble_start_scan (UINT8 filter_enable)
{
    tBTM_BLE_INQ_CB *p_inq = &btm_cb.ble_ctr_cb.inq_var;
    tBTM_STATUS status = BTM_CMD_STARTED;
<span class="token comment">/* start scan, disable duplicate filtering */</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>btsnd_hcic_ble_set_scan_enable <span class="token punctuation">(</span>BTM_BLE_SCAN_ENABLE<span class="token punctuation">,</span> filter_enable<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
    status <span class="token operator">=</span> BTM_NO_RESOURCES<span class="token punctuation">;</span>
    btm_cb<span class="token punctuation">.</span>ble_ctr_cb<span class="token punctuation">.</span>wl_state <span class="token operator">&amp;</span><span class="token operator">=</span> <span class="token operator">~</span>BTM_BLE_WL_SCAN<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">return</span> status<span class="token punctuation">;</span>

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

Hciblecmds.c (external\bluetooth\bluedroid\stack\hcic)

BOOLEAN btsnd_hcic_ble_set_scan_enable (UINT8 scan_enable, UINT8 duplicate)
{
    BT_HDR *p;
    UINT8 *pp;
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token punctuation">(</span>p <span class="token operator">=</span> <span class="token function">HCI_GET_CMD_BUF</span><span class="token punctuation">(</span>HCIC_PARAM_SIZE_BLE_WRITE_SCAN_ENABLE<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">==</span> <span class="token constant">NULL</span><span class="token punctuation">)</span>
    <span class="token keyword">return</span> <span class="token punctuation">(</span>FALSE<span class="token punctuation">)</span><span class="token punctuation">;</span>

pp <span class="token operator">=</span> <span class="token punctuation">(</span>UINT8 <span class="token operator">*</span><span class="token punctuation">)</span><span class="token punctuation">(</span>p <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Point to data []</span>

p<span class="token operator">-</span><span class="token operator">&gt;</span>len    <span class="token operator">=</span> HCIC_PREAMBLE_SIZE <span class="token operator">+</span> HCIC_PARAM_SIZE_BLE_WRITE_SCAN_ENABLE<span class="token punctuation">;</span>
p<span class="token operator">-</span><span class="token operator">&gt;</span>offset <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>

UINT16_TO_STREAM <span class="token punctuation">(</span>pp<span class="token punctuation">,</span> HCI_BLE_WRITE_SCAN_ENABLE<span class="token punctuation">)</span><span class="token punctuation">;</span>
UINT8_TO_STREAM  <span class="token punctuation">(</span>pp<span class="token punctuation">,</span> HCIC_PARAM_SIZE_BLE_WRITE_SCAN_ENABLE<span class="token punctuation">)</span><span class="token punctuation">;</span>

UINT8_TO_STREAM <span class="token punctuation">(</span>pp<span class="token punctuation">,</span> scan_enable<span class="token punctuation">)</span><span class="token punctuation">;</span>
UINT8_TO_STREAM <span class="token punctuation">(</span>pp<span class="token punctuation">,</span> duplicate<span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">/* Send hci command */</span>
btu_hcif_send_cmd <span class="token punctuation">(</span>LOCAL_BR_EDR_CONTROLLER_ID<span class="token punctuation">,</span>  p<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> <span class="token punctuation">(</span>TRUE<span class="token punctuation">)</span><span class="token punctuation">;</span>

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
3) Start scan timer
void btu_start_timer (TIMER_LIST_ENT *p_tle, UINT16 type, UINT32 timeout)
{
    BT_HDR *p_msg;
    GKI_disable();
<span class="token comment">//If btu timer polling stops, count polling is restarted with a polling cycle of 1s</span>
<span class="token comment">/* if timer list is currently empty, start periodic GKI timer */</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>btu_cb<span class="token punctuation">.</span>timer_queue<span class="token punctuation">.</span>p_first <span class="token operator">==</span> <span class="token constant">NULL</span><span class="token punctuation">)</span>
<span class="token punctuation">{<!-- --></span>
    <span class="token comment">/* if timer starts on other than BTU task */</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">GKI_get_taskid</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">!=</span> BTU_TASK<span class="token punctuation">)</span>
    <span class="token punctuation">{<!-- --></span>
        <span class="token comment">/* post event to start timer in BTU task */</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token punctuation">(</span>p_msg <span class="token operator">=</span> <span class="token punctuation">(</span>BT_HDR <span class="token operator">*</span><span class="token punctuation">)</span><span class="token function">GKI_getbuf</span><span class="token punctuation">(</span>BT_HDR_SIZE<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">!=</span> <span class="token constant">NULL</span><span class="token punctuation">)</span>
        <span class="token punctuation">{<!-- --></span>
            p_msg<span class="token operator">-</span><span class="token operator">&gt;</span>event <span class="token operator">=</span> BT_EVT_TO_START_TIMER<span class="token punctuation">;</span>
            GKI_send_msg <span class="token punctuation">(</span>BTU_TASK<span class="token punctuation">,</span> TASK_MBOX_0<span class="token punctuation">,</span> p_msg<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
    <span class="token keyword">else</span>
    <span class="token punctuation">{<!-- --></span>
        <span class="token comment">/* Start free running 1 second timer for list management */</span>
        GKI_start_timer <span class="token punctuation">(</span>TIMER_0<span class="token punctuation">,</span> GKI_SECS_TO_TICKS <span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">,</span> TRUE<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

GKI_remove_from_timer_list <span class="token punctuation">(</span><span class="token operator">&amp;</span>btu_cb<span class="token punctuation">.</span>timer_queue<span class="token punctuation">,</span> p_tle<span class="token punctuation">)</span><span class="token punctuation">;</span>

p_tle<span class="token operator">-</span><span class="token operator">&gt;</span>event <span class="token operator">=</span> type<span class="token punctuation">;</span>
p_tle<span class="token operator">-</span><span class="token operator">&gt;</span>ticks <span class="token operator">=</span> timeout<span class="token punctuation">;</span>
p_tle<span class="token operator">-</span><span class="token operator">&gt;</span>ticks_initial <span class="token operator">=</span> timeout<span class="token punctuation">;</span>

<span class="token comment">//Add timer to GKI timer list</span>
GKI_add_to_timer_list <span class="token punctuation">(</span><span class="token operator">&amp;</span>btu_cb<span class="token punctuation">.</span>timer_queue<span class="token punctuation">,</span> p_tle<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">GKI_enable</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

If the timer queue of btu task is empty, it means that the timing polling of the current btu task has stopped. Therefore, to start the timing polling of btu task, the polling cycle is 1s. Finally, add the timer to the GKI timer list.
So where does the timer timeout execute? We found GKI_init function:
Gki_ulinux.c (external\bluetooth\bluedroid\gki\ulinux)
As can be seen from the following code, the timer expiration execution function is bt_alarm_cb:

void GKI_init(void)
{
    pthread_mutexattr_t attr;
    tGKI_OS             *p_os;
memset <span class="token punctuation">(</span><span class="token operator">&amp;</span>gki_cb<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> <span class="token keyword">sizeof</span> <span class="token punctuation">(</span>gki_cb<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token function">gki_buffer_init</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">gki_timers_init</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">alarm_service_init</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
gki_cb<span class="token punctuation">.</span>com<span class="token punctuation">.</span>OSTicks <span class="token operator">=</span> <span class="token punctuation">(</span>UINT32<span class="token punctuation">)</span> <span class="token function">times</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">pthread_mutexattr_init</span><span class="token punctuation">(</span><span class="token operator">&amp;</span>attr<span class="token punctuation">)</span><span class="token punctuation">;</span>
p_os <span class="token operator">=</span> <span class="token operator">&amp;</span>gki_cb<span class="token punctuation">.</span>os<span class="token punctuation">;</span>
<span class="token function">pthread_mutex_init</span><span class="token punctuation">(</span><span class="token operator">&amp;</span>p_os<span class="token operator">-</span><span class="token operator">&gt;</span>GKI_mutex<span class="token punctuation">,</span> <span class="token operator">&amp;</span>attr<span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token keyword">struct</span> sigevent sigevent<span class="token punctuation">;</span>
<span class="token function">memset</span><span class="token punctuation">(</span><span class="token operator">&amp;</span>sigevent<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> <span class="token keyword">sizeof</span><span class="token punctuation">(</span>sigevent<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
sigevent<span class="token punctuation">.</span>sigev_notify <span class="token operator">=</span> SIGEV_THREAD<span class="token punctuation">;</span>
sigevent<span class="token punctuation">.</span>sigev_notify_function <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token keyword">void</span> <span class="token punctuation">(</span><span class="token operator">*</span><span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token keyword">union</span> sigval<span class="token punctuation">)</span><span class="token punctuation">)</span>bt_alarm_cb<span class="token punctuation">;</span>
sigevent<span class="token punctuation">.</span>sigev_value<span class="token punctuation">.</span>sival_ptr <span class="token operator">=</span> <span class="token constant">NULL</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">timer_create</span><span class="token punctuation">(</span>CLOCK_REALTIME<span class="token punctuation">,</span> <span class="token operator">&amp;</span>sigevent<span class="token punctuation">,</span> <span class="token operator">&amp;</span>posix_timer<span class="token punctuation">)</span> <span class="token operator">==</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
    <span class="token function">ALOGE</span><span class="token punctuation">(</span><span class="token string">"%s unable to create POSIX timer: %s"</span><span class="token punctuation">,</span> <span class="token constant">__func__</span><span class="token punctuation">,</span> <span class="token function">strerror</span><span class="token punctuation">(</span>errno<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    timer_created <span class="token operator">=</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{<!-- --></span>
    timer_created <span class="token operator">=</span> <span class="token boolean">true</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

}

/** Callback from Java thread after alarm from AlarmService fires. /
static void bt_alarm_cb(void data)
{
GKI_timer_update(ticks_taken > alarm_service.ticks_scheduled
? ticks_taken : alarm_service.ticks_scheduled);
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35

Gki_time.c (external\bluetooth\bluedroid\gki\common) 25288 2017/12/14

void GKI_timer_update (INT32 ticks_since_last_update)
{
    UINT8   task_id;
    long    next_expiration; 
gki_cb<span class="token punctuation">.</span>com<span class="token punctuation">.</span>OSTicks <span class="token operator">+</span><span class="token operator">=</span> ticks_since_last_update<span class="token punctuation">;</span>
gki_cb<span class="token punctuation">.</span>com<span class="token punctuation">.</span>OSTicksTilExp <span class="token operator">-</span><span class="token operator">=</span> ticks_since_last_update<span class="token punctuation">;</span>

<span class="token comment">/* Don't allow timer interrupt nesting */</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>gki_cb<span class="token punctuation">.</span>com<span class="token punctuation">.</span>timer_nesting<span class="token punctuation">)</span>
    <span class="token keyword">return</span><span class="token punctuation">;</span>

gki_cb<span class="token punctuation">.</span>com<span class="token punctuation">.</span>timer_nesting <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span>
next_expiration <span class="token operator">=</span> GKI_NO_NEW_TMRS_STARTED<span class="token punctuation">;</span>
gki_cb<span class="token punctuation">.</span>com<span class="token punctuation">.</span>OSNumOrigTicks <span class="token operator">-</span><span class="token operator">=</span> gki_cb<span class="token punctuation">.</span>com<span class="token punctuation">.</span>OSTicksTilExp<span class="token punctuation">;</span>
<span class="token function">GKI_disable</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">/* Check for OS Task Timers */</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span>task_id <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> task_id <span class="token operator">&lt;</span> GKI_MAX_TASKS<span class="token punctuation">;</span> task_id<span class="token operator">++</span><span class="token punctuation">)</span>
<span class="token punctuation">{<!-- --></span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>gki_cb<span class="token punctuation">.</span>com<span class="token punctuation">.</span>OSWaitTmr<span class="token punctuation">[</span>task_id<span class="token punctuation">]</span> <span class="token operator">&gt;</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token comment">/* If timer is running */</span>
    <span class="token punctuation">{<!-- --></span>
        gki_cb<span class="token punctuation">.</span>com<span class="token punctuation">.</span>OSWaitTmr<span class="token punctuation">[</span>task_id<span class="token punctuation">]</span> <span class="token operator">-</span><span class="token operator">=</span> gki_cb<span class="token punctuation">.</span>com<span class="token punctuation">.</span>OSNumOrigTicks<span class="token punctuation">;</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>gki_cb<span class="token punctuation">.</span>com<span class="token punctuation">.</span>OSWaitTmr<span class="token punctuation">[</span>task_id<span class="token punctuation">]</span> <span class="token operator">&lt;=</span> <span class="token number">0</span><span class="token punctuation">)</span>
        <span class="token punctuation">{<!-- --></span>
            <span class="token comment">/* Timer Expired */</span>
            gki_cb<span class="token punctuation">.</span>com<span class="token punctuation">.</span>OSRdyTbl<span class="token punctuation">[</span>task_id<span class="token punctuation">]</span> <span class="token operator">=</span> TASK_READY<span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>

#if (GKI_NUM_TIMERS > 0)
/* If any timer is running, decrement */
if (gki_cb.com.OSTaskTmr0[task_id] > 0)
{
gki_cb.com.OSTaskTmr0[task_id] -= gki_cb.com.OSNumOrigTicks;

        <span class="token keyword">if</span> <span class="token punctuation">(</span>gki_cb<span class="token punctuation">.</span>com<span class="token punctuation">.</span>OSTaskTmr0<span class="token punctuation">[</span>task_id<span class="token punctuation">]</span> <span class="token operator">&lt;=</span> <span class="token number">0</span><span class="token punctuation">)</span>
        <span class="token punctuation">{<!-- --></span>
            <span class="token comment">/* Reload timer and set Timer 0 Expired event mask */</span>
            gki_cb<span class="token punctuation">.</span>com<span class="token punctuation">.</span>OSTaskTmr0<span class="token punctuation">[</span>task_id<span class="token punctuation">]</span> <span class="token operator">=</span> gki_cb<span class="token punctuation">.</span>com<span class="token punctuation">.</span>OSTaskTmr0R<span class="token punctuation">[</span>task_id<span class="token punctuation">]</span><span class="token punctuation">;</span>
            GKI_send_event <span class="token punctuation">(</span>task_id<span class="token punctuation">,</span> TIMER_0_EVT_MASK<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>

    <span class="token comment">/* Check to see if this timer is the next one to expire */</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>gki_cb<span class="token punctuation">.</span>com<span class="token punctuation">.</span>OSTaskTmr0<span class="token punctuation">[</span>task_id<span class="token punctuation">]</span> <span class="token operator">&gt;</span> <span class="token number">0</span> <span class="token operator">&amp;&amp;</span> gki_cb<span class="token punctuation">.</span>com<span class="token punctuation">.</span>OSTaskTmr0<span class="token punctuation">[</span>task_id<span class="token punctuation">]</span> <span class="token operator">&lt;</span> next_expiration<span class="token punctuation">)</span>
        next_expiration <span class="token operator">=</span> gki_cb<span class="token punctuation">.</span>com<span class="token punctuation">.</span>OSTaskTmr0<span class="token punctuation">[</span>task_id<span class="token punctuation">]</span><span class="token punctuation">;</span>

#endif
//Timer is omitted here_ 1,TIMER_2,TIMER_3. Relevant treatment
}
/* Set the next timer experation value if there is one to start */
if (next_expiration < GKI_NO_NEW_TMRS_STARTED)
{
gki_cb.com.OSTicksTilExp = gki_cb.com.OSNumOrigTicks = next_expiration;
}
else
{
gki_cb.com.OSTicksTilExp = gki_cb.com.OSNumOrigTicks = 0;
}

<span class="token comment">// Set alarm service for next alarm.</span>
<span class="token function">alarm_service_reschedule</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">GKI_enable</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
gki_cb<span class="token punctuation">.</span>com<span class="token punctuation">.</span>timer_nesting <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
<span class="token keyword">return</span><span class="token punctuation">;</span>

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67

If OSTaskTmr is less than 0, it indicates that the timer has timed out, and GKI is called here_ send_ Event sent an event out.

Btu_task.c (external\bluetooth\bluedroid\stack\btu)

BTU_API UINT32 btu_task (UINT32 param)
{
    /* Wait for, and process, events */
    for (;;)
    {
        event = GKI_wait (0xFFFF, 0);
    <span class="token keyword">if</span> <span class="token punctuation">(</span>event <span class="token operator">&amp;</span> TIMER_0_EVT_MASK<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
        GKI_update_timer_list <span class="token punctuation">(</span><span class="token operator">&amp;</span>btu_cb<span class="token punctuation">.</span>timer_queue<span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

        <span class="token keyword">while</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token function">GKI_timer_queue_is_empty</span><span class="token punctuation">(</span><span class="token operator">&amp;</span>btu_cb<span class="token punctuation">.</span>timer_queue<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
            TIMER_LIST_ENT <span class="token operator">*</span>p_tle <span class="token operator">=</span> <span class="token function">GKI_timer_getfirst</span><span class="token punctuation">(</span><span class="token operator">&amp;</span>btu_cb<span class="token punctuation">.</span>timer_queue<span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">if</span> <span class="token punctuation">(</span>p_tle<span class="token operator">-</span><span class="token operator">&gt;</span>ticks <span class="token operator">!=</span> <span class="token number">0</span><span class="token punctuation">)</span>
                <span class="token keyword">break</span><span class="token punctuation">;</span>

            <span class="token function">GKI_remove_from_timer_list</span><span class="token punctuation">(</span><span class="token operator">&amp;</span>btu_cb<span class="token punctuation">.</span>timer_queue<span class="token punctuation">,</span> p_tle<span class="token punctuation">)</span><span class="token punctuation">;</span>

            <span class="token keyword">switch</span> <span class="token punctuation">(</span>p_tle<span class="token operator">-</span><span class="token operator">&gt;</span>event<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>

#if (defined(BLE_INCLUDED) && BLE_INCLUDED == TRUE)
case BTU_TTYPE_BLE_INQUIRY:
case BTU_TTYPE_BLE_GAP_LIM_DISC:
case BTU_TTYPE_BLE_GAP_FAST_ADV:
case BTU_TTYPE_BLE_OBSERVE:
btm_ble_timeout(p_tle);
break;

                <span class="token keyword">case</span> BTU_TTYPE_ATT_WAIT_FOR_RSP<span class="token operator">:</span>
                    <span class="token function">gatt_rsp_timeout</span><span class="token punctuation">(</span>p_tle<span class="token punctuation">)</span><span class="token punctuation">;</span>
                    <span class="token keyword">break</span><span class="token punctuation">;</span>
            <span class="token punctuation">}</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>

#if defined(QUICK_TIMER_TICKS_PER_SEC) && (QUICK_TIMER_TICKS_PER_SEC > 0)
if (event & TIMER_2_EVT_MASK)
{
btu_process_quick_timer_evt();
}
#endif

#if (defined(BTU_BTA_INCLUDED) && BTU_BTA_INCLUDED == TRUE)
if (event & TIMER_1_EVT_MASK)
{
bta_sys_timer_update();
}
#endif

    <span class="token keyword">if</span> <span class="token punctuation">(</span>event <span class="token operator">&amp;</span> TIMER_3_EVT_MASK<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
        <span class="token function">BTM_TRACE_API</span><span class="token punctuation">(</span><span class="token string">"Received oneshot timer event complete"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

<span class="token keyword">return</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54

The timer event type for starting the scan is BTU_TTYPE_BLE_INQUIRY,btm_ble_timeout is called, and finally BTM is called_ ble_ stop_ Scan stops scanning.
Btm_ble_gap.c (external\bluetooth\bluedroid\stack\btm)

void btm_ble_timeout(TIMER_LIST_ENT *p_tle)
{
    switch (p_tle->event)
    {
            case BTU_TTYPE_BLE_INQUIRY:
            btm_ble_stop_inquiry();
            	btm_ble_stop_scan(); // Stop scanning
            break;
    }
}

 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

So far, the three things that started the scan have been tracked and completed. Now let's continue the analysis.
BTU is called at the end of setting scanning parameters and starting scanning_ hcif_ send_ CMD sends hci command,
Let's trace this function.
Btu_hcif.c (external\bluetooth\bluedroid\stack\btu)

/*******************************************************************************
**
** Function         btu_hcif_send_cmd
**
** Description      This function is called to check if it can send commands
**                  to the Host Controller. It may be passed the address of
**                  a packet to send.
**
** Returns          void
**
*******************************************************************************/
void btu_hcif_send_cmd (UINT8 controller_id, BT_HDR *p_buf)
{
    tHCI_CMD_CB * p_hci_cmd_cb = &(btu_cb.hci_cmd_cb[controller_id]);
<span class="token comment">/* If there are already commands in the queue, then enqueue this command */</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token punctuation">(</span>p_buf<span class="token punctuation">)</span> <span class="token operator">&amp;&amp;</span> <span class="token punctuation">(</span>p_hci_cmd_cb<span class="token operator">-</span><span class="token operator">&gt;</span>cmd_xmit_q<span class="token punctuation">.</span>count<span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">{<!-- --></span>
    GKI_enqueue <span class="token punctuation">(</span><span class="token operator">&amp;</span><span class="token punctuation">(</span>p_hci_cmd_cb<span class="token operator">-</span><span class="token operator">&gt;</span>cmd_xmit_q<span class="token punctuation">)</span><span class="token punctuation">,</span> p_buf<span class="token punctuation">)</span><span class="token punctuation">;</span>
    p_buf <span class="token operator">=</span> <span class="token constant">NULL</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token comment">/* Allow for startup case, where no acks may be received */</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span> <span class="token punctuation">(</span><span class="token punctuation">(</span>controller_id <span class="token operator">==</span> LOCAL_BR_EDR_CONTROLLER_ID<span class="token punctuation">)</span>
     <span class="token operator">&amp;&amp;</span> <span class="token punctuation">(</span>p_hci_cmd_cb<span class="token operator">-</span><span class="token operator">&gt;</span>cmd_window <span class="token operator">==</span> <span class="token number">0</span><span class="token punctuation">)</span>
     <span class="token operator">&amp;&amp;</span> <span class="token punctuation">(</span>btm_cb<span class="token punctuation">.</span>devcb<span class="token punctuation">.</span>state <span class="token operator">==</span> BTM_DEV_STATE_WAIT_RESET_CMPLT<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">)</span>
<span class="token punctuation">{<!-- --></span>
    p_hci_cmd_cb<span class="token operator">-</span><span class="token operator">&gt;</span>cmd_window <span class="token operator">=</span> p_hci_cmd_cb<span class="token operator">-</span><span class="token operator">&gt;</span>cmd_xmit_q<span class="token punctuation">.</span>count <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token comment">/* See if we can send anything */</span>
<span class="token keyword">while</span> <span class="token punctuation">(</span>p_hci_cmd_cb<span class="token operator">-</span><span class="token operator">&gt;</span>cmd_window <span class="token operator">!=</span> <span class="token number">0</span><span class="token punctuation">)</span>
<span class="token punctuation">{<!-- --></span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>p_buf<span class="token punctuation">)</span>
        p_buf <span class="token operator">=</span> <span class="token punctuation">(</span>BT_HDR <span class="token operator">*</span><span class="token punctuation">)</span>GKI_dequeue <span class="token punctuation">(</span><span class="token operator">&amp;</span><span class="token punctuation">(</span>p_hci_cmd_cb<span class="token operator">-</span><span class="token operator">&gt;</span>cmd_xmit_q<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token keyword">if</span> <span class="token punctuation">(</span>p_buf<span class="token punctuation">)</span>
    <span class="token punctuation">{<!-- --></span>
        <span class="token function">btu_hcif_store_cmd</span><span class="token punctuation">(</span>controller_id<span class="token punctuation">,</span> p_buf<span class="token punctuation">)</span><span class="token punctuation">;</span>
        p_hci_cmd_cb<span class="token operator">-</span><span class="token operator">&gt;</span>cmd_window<span class="token operator">--</span><span class="token punctuation">;</span>

        <span class="token keyword">if</span> <span class="token punctuation">(</span>controller_id <span class="token operator">==</span> LOCAL_BR_EDR_CONTROLLER_ID<span class="token punctuation">)</span>
        <span class="token punctuation">{<!-- --></span>
            <span class="token function">HCI_CMD_TO_LOWER</span><span class="token punctuation">(</span>p_buf<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
        <span class="token keyword">else</span>
        <span class="token punctuation">{<!-- --></span>
            <span class="token function">GKI_freebuf</span><span class="token punctuation">(</span>p_buf<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>

        p_buf <span class="token operator">=</span> <span class="token constant">NULL</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    <span class="token keyword">else</span>
        <span class="token keyword">break</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token keyword">if</span> <span class="token punctuation">(</span>p_buf<span class="token punctuation">)</span>
    GKI_enqueue <span class="token punctuation">(</span><span class="token operator">&amp;</span><span class="token punctuation">(</span>p_hci_cmd_cb<span class="token operator">-</span><span class="token operator">&gt;</span>cmd_xmit_q<span class="token punctuation">)</span><span class="token punctuation">,</span> p_buf<span class="token punctuation">)</span><span class="token punctuation">;</span>

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59

View HCI_CMD_TO_LOWER definition:

/* Sends an HCI command received from the upper stack to the BD/EDR HCI transport. */
#ifndef HCI_CMD_TO_LOWER
#define HCI_CMD_TO_LOWER(p)         bte_main_hci_send((BT_HDR *)(p), BT_EVT_TO_LM_HCI_CMD);
#endif

 
  • 1
  • 2
  • 3
  • 4

Bte_main.c (external\bluetooth\bluedroid\main)

void bte_main_hci_send (BT_HDR *p_msg, UINT16 event)
{
    UINT16 sub_event = event & BT_SUB_EVT_MASK;  /* local controller ID */
p_msg<span class="token operator">-</span><span class="token operator">&gt;</span>event <span class="token operator">=</span> event<span class="token punctuation">;</span>
<span class="token keyword">if</span><span class="token punctuation">(</span><span class="token punctuation">(</span>sub_event <span class="token operator">==</span> LOCAL_BR_EDR_CONTROLLER_ID<span class="token punctuation">)</span> <span class="token operator">||</span> \
   <span class="token punctuation">(</span>sub_event <span class="token operator">==</span> LOCAL_BLE_CONTROLLER_ID<span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">{<!-- --></span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>bt_hc_if<span class="token punctuation">)</span>
        bt_hc_if<span class="token operator">-</span><span class="token operator">&gt;</span><span class="token function">transmit_buf</span><span class="token punctuation">(</span><span class="token punctuation">(</span>TRANSAC<span class="token punctuation">)</span>p_msg<span class="token punctuation">,</span> \
                                   <span class="token punctuation">(</span><span class="token keyword">char</span> <span class="token operator">*</span><span class="token punctuation">)</span> <span class="token punctuation">(</span>p_msg <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">,</span> \
                                    p_msg<span class="token operator">-</span><span class="token operator">&gt;</span>len<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">else</span>
        <span class="token function">GKI_freebuf</span><span class="token punctuation">(</span>p_msg<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

View BT_ hc_ Assignment of if:

static void bte_main_in_hw_init(void)
{
	// bt_ hci_ Bluetooth hclibinterface in bdroid. C
    if ( (bt_hc_if = (bt_hc_interface_t *) bt_hc_get_interface()) \
         == NULL)
    {
        APPL_TRACE_ERROR("!!! Failed to get BtHostControllerInterface !!!");
    }
<span class="token function">memset</span><span class="token punctuation">(</span><span class="token operator">&amp;</span>preload_retry_cb<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> <span class="token keyword">sizeof</span><span class="token punctuation">(</span>bt_preload_retry_cb_t<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

Bt_hci_bdroid.c (external/bluetooth/bluedroid/hci/src)

void bthc_tx(HC_BT_HDR *buf) {
  pthread_mutex_lock(&hc_cb.worker_thread_lock);
  if (hc_cb.worker_thread) {
    if (buf)
      utils_enqueue(&tx_q, buf); // Put buf in queue tx_q. Give to event_tx processing
    // Construct a work_item_t and put in thread - > work_ queue,
    // worker_thread processing function run of thread_ Thread will start from thread - > work_ Take the item from the queue,
    // And call the callback function event_tx
    thread_post(hc_cb.worker_thread, event_tx, NULL); 
  }

pthread_mutex_unlock(&hc_cb.worker_thread_lock);
}
/** Transmit frame /
static int transmit_buf(TRANSAC transac, UNUSED_ATTR char p_buf, UNUSED_ATTR int len) {
bthc_tx((HC_BT_HDR *)transac);
return BT_HC_STATUS_SUCCESS;
}

static const bt_hc_interface_t bluetoothHCLibInterface = {
sizeof(bt_hc_interface_t),
init,
set_power,
lpm,
preload,
postload,
transmit_buf,
logging,
cleanup,
tx_hc_cmd,
};

const bt_hc_interface_t *bt_hc_get_interface(void)
{
return &bluetoothHCLibInterface;
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

Let's mainly look at the actual sending function event_tx:
event_ There is a while loop in TX through utils_getnext from tx_q get all messages and save to sending_msg_que, the number of messages is sending_msg_count. After getting the message, jump out of while, use a for loop to get all the messages to be sent, and call P_ hci_ If - > send.
Note: if we have run out of unused HCI command credit for the controller (usually 1), all HCI command packets in the queue are skipped.

static void event_tx(UNUSED_ATTR void *context) {
  /*
   *  We will go through every packets in the tx queue.
   *  Fine to clear tx_cmd_pkts_pending.
   */
  tx_cmd_pkts_pending = false;
  HC_BT_HDR *sending_msg_que[64];
  size_t sending_msg_count = 0;
  int sending_hci_cmd_pkts_count = 0;
  utils_lock();
  HC_BT_HDR *p_next_msg = tx_q.p_first;
  while (p_next_msg && sending_msg_count < ARRAY_SIZE(sending_msg_que))
  {
  	// Note: if we have run out of unused HCI command credit for the controller (usually 1),
  	// All HCI command packets in the queue are skipped.
    if ((p_next_msg->event & MSG_EVT_MASK)==MSG_STACK_TO_HC_HCI_CMD)
    {
      if (tx_cmd_pkts_pending ||
          (sending_hci_cmd_pkts_count >= num_hci_cmd_pkts))
      {
        tx_cmd_pkts_pending = true;
        p_next_msg = utils_getnext(p_next_msg); // Fetch message
        continue;
      }
      sending_hci_cmd_pkts_count++; //Increase message count sending_msg_count
    }
HC_BT_HDR <span class="token operator">*</span>p_msg <span class="token operator">=</span> p_next_msg<span class="token punctuation">;</span>
p_next_msg <span class="token operator">=</span> <span class="token function">utils_getnext</span><span class="token punctuation">(</span>p_msg<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Fetch message</span>
<span class="token function">utils_remove_from_queue_unlocked</span><span class="token punctuation">(</span><span class="token operator">&amp;</span>tx_q<span class="token punctuation">,</span> p_msg<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">//Put the message into sending_msg_que and increase the message count sending_ msg_ count</span>
sending_msg_que<span class="token punctuation">[</span>sending_msg_count<span class="token operator">++</span><span class="token punctuation">]</span> <span class="token operator">=</span> p_msg<span class="token punctuation">;</span> 

}
utils_unlock();
for(size_t i = 0; i < sending_msg_count; i++)
p_hci_if->send(sending_msg_que[i]);
if (tx_cmd_pkts_pending)
BTHCDBG("Used up Tx Cmd credits");
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39

p_hci_if is assigned in init function:

static int init(const bt_hc_callbacks_t* p_cb, unsigned char *local_bdaddr)
	extern tHCI_IF hci_mct_func_table;
	p_hci_if = &hci_h4_func_table

 
  • 1
  • 2
  • 3

Hci_h4.c (external\bluetooth\bluedroid\hci\src)

/******************************************************************************
**  HCI H4 Services interface table
******************************************************************************/
const tHCI_IF hci_h4_func_table =
{
    hci_h4_init,
    hci_h4_cleanup,
    hci_h4_send_msg,
    hci_h4_send_int_cmd,
    hci_h4_get_acl_data_length,
    hci_h4_receive_msg
};

/*******************************************************************************
** Function hci_h4_send_msg
** Description Determine message type, set HCI H4 packet indicator, and
** send message through USERIAL driver
****************************************************************************/
void hci_h4_send_msg(HC_BT_HDR p_msg)
{
uint8_t type = 0;
uint16_t handle;
uint16_t bytes_to_send, lay_spec;
uint8_t p = ((uint8_t )(p_msg + 1)) + p_msg->offset;
uint16_ t event = p_ msg->event & MSG_ EVT_ MASK;// Event type
uint16_ t sub_ event = p_ msg->event & MSG_ SUB_ EVT_ MASK; // sub_ Event type
uint16_t acl_pkt_size = 0, acl_data_size = 0;
uint16_t bytes_sent;

<span class="token comment">/* wake up BT device if its in sleep mode */</span>
<span class="token function">lpm_wake_assert</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token keyword">if</span> <span class="token punctuation">(</span>event <span class="token operator">==</span> MSG_STACK_TO_HC_HCI_ACL<span class="token punctuation">)</span>
    type <span class="token operator">=</span> H4_TYPE_ACL_DATA<span class="token punctuation">;</span>
<span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>event <span class="token operator">==</span> MSG_STACK_TO_HC_HCI_SCO<span class="token punctuation">)</span>
    type <span class="token operator">=</span> H4_TYPE_SCO_DATA<span class="token punctuation">;</span>
<span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>event <span class="token operator">==</span> MSG_STACK_TO_HC_HCI_CMD<span class="token punctuation">)</span>
    type <span class="token operator">=</span> H4_TYPE_COMMAND<span class="token punctuation">;</span>

<span class="token keyword">if</span> <span class="token punctuation">(</span>sub_event <span class="token operator">==</span> LOCAL_BR_EDR_CONTROLLER_ID<span class="token punctuation">)</span>
<span class="token punctuation">{<!-- --></span>
    acl_data_size <span class="token operator">=</span> h4_cb<span class="token punctuation">.</span>hc_acl_data_size<span class="token punctuation">;</span>
    acl_pkt_size <span class="token operator">=</span> h4_cb<span class="token punctuation">.</span>hc_acl_data_size <span class="token operator">+</span> HCI_ACL_PREAMBLE_SIZE<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">else</span>
<span class="token punctuation">{<!-- --></span>
    acl_data_size <span class="token operator">=</span> h4_cb<span class="token punctuation">.</span>hc_ble_acl_data_size<span class="token punctuation">;</span>
    acl_pkt_size <span class="token operator">=</span> h4_cb<span class="token punctuation">.</span>hc_ble_acl_data_size <span class="token operator">+</span> HCI_ACL_PREAMBLE_SIZE<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

  <span class="token comment">/* Do all the first chunks */</span>
  <span class="token keyword">while</span> <span class="token punctuation">(</span>p_msg<span class="token operator">-</span><span class="token operator">&gt;</span>len <span class="token operator">&gt;</span> acl_pkt_size<span class="token punctuation">)</span>
  <span class="token punctuation">{<!-- --></span> 
    <span class="token comment">/* Check if sending ACL data that needs fragmenting */</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token punctuation">(</span>event <span class="token operator">==</span> MSG_STACK_TO_HC_HCI_ACL<span class="token punctuation">)</span> <span class="token operator">&amp;&amp;</span> <span class="token punctuation">(</span>p_msg<span class="token operator">-</span><span class="token operator">&gt;</span>len <span class="token operator">&gt;</span> acl_pkt_size<span class="token punctuation">)</span><span class="token punctuation">)</span>
    <span class="token punctuation">{<!-- --></span>
            bytes_to_send <span class="token operator">=</span> acl_pkt_size <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">;</span> 
            <span class="token comment">/* Send command / data via uart */</span>
            bytes_sent <span class="token operator">=</span> <span class="token function">userial_write</span><span class="token punctuation">(</span>event<span class="token punctuation">,</span><span class="token punctuation">(</span><span class="token keyword">uint8_t</span> <span class="token operator">*</span><span class="token punctuation">)</span> p<span class="token punctuation">,</span>bytes_to_send<span class="token punctuation">)</span><span class="token punctuation">;</span>
            	<span class="token function">write</span><span class="token punctuation">(</span>userial_cb<span class="token punctuation">.</span>fd<span class="token punctuation">,</span> p_data <span class="token operator">+</span> total<span class="token punctuation">,</span> len<span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token comment">/* Generate btsnoop tracking message */</span>
            <span class="token function">btsnoop_capture</span><span class="token punctuation">(</span>p_msg<span class="token punctuation">,</span> <span class="token boolean">false</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
p <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token keyword">uint8_t</span> <span class="token operator">*</span><span class="token punctuation">)</span><span class="token punctuation">(</span>p_msg <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">+</span> p_msg<span class="token operator">-</span><span class="token operator">&gt;</span>offset <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">;</span>
<span class="token operator">*</span>p <span class="token operator">=</span> type<span class="token punctuation">;</span>
bytes_to_send <span class="token operator">=</span> p_msg<span class="token operator">-</span><span class="token operator">&gt;</span>len <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">;</span> 
<span class="token comment">/* Send command / data via uart */</span>
bytes_sent <span class="token operator">=</span> <span class="token function">userial_write</span><span class="token punctuation">(</span>event<span class="token punctuation">,</span><span class="token punctuation">(</span><span class="token keyword">uint8_t</span> <span class="token operator">*</span><span class="token punctuation">)</span> p<span class="token punctuation">,</span> bytes_to_send<span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token function">write</span><span class="token punctuation">(</span>userial_cb<span class="token punctuation">.</span>fd<span class="token punctuation">,</span> p_data <span class="token operator">+</span> total<span class="token punctuation">,</span> len<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">/* Generate btsnoop tracking message */</span>
<span class="token function">btsnoop_capture</span><span class="token punctuation">(</span>p_msg<span class="token punctuation">,</span> <span class="token boolean">false</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token keyword">if</span> <span class="token punctuation">(</span>bt_hc_cbacks<span class="token punctuation">)</span>
<span class="token punctuation">{<!-- --></span>
	<span class="token comment">// Callback BTE_ HC in main. C_ cbacks-> tx_ result</span>
    bt_hc_cbacks<span class="token operator">-</span><span class="token operator">&gt;</span><span class="token function">tx_result</span><span class="token punctuation">(</span><span class="token punctuation">(</span>TRANSAC<span class="token punctuation">)</span> p_msg<span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token keyword">char</span> <span class="token operator">*</span><span class="token punctuation">)</span> <span class="token punctuation">(</span>p_msg <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">,</span> \
                                BT_HC_TX_SUCCESS<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token keyword">return</span><span class="token punctuation">;</span>

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82

hci_h4_send_msg mainly works as follows:
1) Get event and sub according to the event of the message_ event
2) Get the hci type according to event, and get the hci type according to sub_event gets acl_data_size and acl_packet_size
3) Send message via uart
4) Generate btsnoop tracking data
5) Callback uart write success status, and the actual command sending status is determined by userial_read_thread to complete.

Userial.c (external\bluetooth\bluedroid\hci\src)

uint16_t userial_write(uint16_t msg_id, const uint8_t *p_data, uint16_t len) {
    UNUSED(msg_id);
    uint16_t total = 0;
    while (len) {
        ssize_t ret = write(userial_cb.fd, p_data + total, len);
        switch (ret) {
            case -1:
                ALOGE("%s error writing to serial port: %s", __func__, strerror(errno));
                return total;
            case 0:  // don't loop forever in case write returns 0.
                return total;
            default:
                total += ret;
                len -= ret;
                break;
        }
    	send_byte_total+=total;    
    }
<span class="token keyword">return</span> total<span class="token punctuation">;</span>

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

View userial_ Assignment of cb.fd:

bool userial_open(userial_port_t port) {
    // Call in to the vendor-specific library to open the serial port.
    int fd_array[CH_MAX];
    int num_ports = vendor_send_command(BT_VND_OP_USERIAL_OPEN, &fd_array);
    userial_cb.fd = fd_array[0];
    userial_cb.port = port;
    if (pthread_create(&userial_cb.read_thread, NULL, userial_read_thread, NULL)) {
        ALOGE("%s unable to spawn read thread.", __func__);
        goto error;
    }
}

 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

Vendor.c (external\bluetooth\bluedroid\hci\src)

int vendor_send_command(bt_vendor_opcode_t opcode, void *param) {
  return vendor_interface->op(opcode, param);
}

 
  • 1
  • 2
  • 3
VENDOR_LIBRARY_NAME = "libbt-vendor.so";
vendor_open(const uint8_t *local_bdaddr) 
    lib_handle = dlopen(VENDOR_LIBRARY_NAME, RTLD_NOW);
    vendor_interface = (bt_vendor_interface_t *)dlsym(lib_handle, VENDOR_LIBRARY_SYMBOL_NAME);

 
  • 1
  • 2
  • 3
  • 4

dlsym returns the address corresponding to the symbol according to the dynamic link library operation handle and symbol.
You can get the vendor_ The implementation code of the interface is in the dynamic link library libbt-vendor.so.

Bt_vendor_brcm.c (hardware\broadcom\libbt\src)
Grab libbt-vendor.so globally. We found the source file contained in libbt-vendor.so in Android.mk under hardware\broadcom\libbt.
Grab it bt_vendor_interface_t. Found in Bt_vendor_brcm.c found its implementation:

// Entry point of DLib
const bt_vendor_interface_t BLUETOOTH_VENDOR_LIB_INTERFACE = {
    sizeof(bt_vendor_interface_t),
    init,
    op,
    	     case BT_VND_OP_USERIAL_OPEN:
                int (*fd_array)[] = (int (*)[]) param;
                int fd, idx;
                fd = userial_vendor_open((tUSERIAL_CFG *) &userial_init_cfg);
                	/* Device port name where Bluetooth controller attached */
					#ifndef BLUETOOTH_UART_DEVICE_PORT // bt_vendor_brcm.h
					#define BLUETOOTH_UART_DEVICE_PORT   "/dev/ttyO1"  // maguro 
					#endif
                	// void userial_ vendor_ Assignment in init:
    				// 		snprintf(vnd_userial.port_name, VND_PORT_NAME_MAXLEN, "%s", BLUETOOTH_UART_DEVICE_PORT);
                	vnd_userial.fd = open(vnd_userial.port_name, O_RDWR);//userial_vendor.c
                	return vnd_userial.fd;
                if (fd != -1)
                {
                    for (idx=0; idx < CH_MAX; idx++)
                        (*fd_array)[idx] = fd;
                retval <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span>
            <span class="token punctuation">}</span>
        <span class="token punctuation">}</span>
cleanup

};

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

Back to hci_h4_send_msg view BT_ hc_ Assignment of cbacks:
Bt_hci_bdroid.c (external\bluetooth\bluedroid\hci\src)

static int init(const bt_hc_callbacks_t* p_cb, unsigned char *local_bdaddr)
    /* store reference to user callbacks */
    bt_hc_cbacks = (bt_hc_callbacks_t *) p_cb;

static const bt_hc_interface_t bluetoothHCLibInterface = {
sizeof(bt_hc_interface_t),
init,
set_power,
lpm,
preload,
postload,
transmit_buf,
logging,
cleanup,
tx_hc_cmd,
};

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

The init function of Bluetooth hclibinterface is called when Bluetooth is enable d:

Bte_main.c (external\bluetooth\bluedroid\main)

bt_hc_callbacks_t *bt_hc_cbacks = NULL;
static const bt_hc_callbacks_t hc_callbacks = {
    sizeof(bt_hc_callbacks_t),
    preload_cb,
    postload_cb,
    lpm_cb,
    hostwake_ind,
    alloc,
    dealloc,
    data_ind,
    tx_result
};

static void bte_main_in_hw_init(void)
{
bt_hc_if = (bt_hc_interface_t *) bt_hc_get_interface() // Bt_hci_bdroid.c
return &bluetoothHCLibInterface;
}

bte_main_enable
bte_hci_enable
//Call the init function of bluetoothHCLibInterface to set bt_hc_cbacks is assigned hc_callbacks
int result = bt_hc_if->init(&hc_callbacks, btif_local_bd_addr.address);
bt_hc_cbacks = (bt_hc_callbacks_t *) p_cb; // Bt_hci_bdroid.c

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

Eventually bt_hc_cbacks is assigned hc_callbacks.

2, APK scan

apk scan occurs after Bluetooth is turned on. It is divided into classic Bluetooth scan and BLE scan.
1) Classic Bluetooth scanning

private BluetoothAdapter mBluetoothAdapter;

// Initializes a Bluetooth adapter. For API level 18 and above, get a reference to
// BluetoothAdapter through BluetoothManager.
final BluetoothManager bluetoothManager =
(BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManager.getAdapter();

//Start scan
mBluetoothAdapter.startDiscovery();

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

The rest is the same as the scanning process in settings.
The scanned devices are sent by broadcast in the deviceFoundCallback method of JniCallbacks.java.
JniCallbacks.java (packages\apps\bluetooth\src\com\android\bluetooth\btservice)

void deviceFoundCallback(byte[] address) 
    mRemoteDevices.deviceFoundCallback(address);
        // The device properties are already registered - we can send the intent
        BluetoothDevice device = getDevice(address); // RemoteDevices.java
        DeviceProperties deviceProp = getDeviceProperties(device);
        Intent intent = new Intent(BluetoothDevice.ACTION_FOUND);
        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
        intent.putExtra(BluetoothDevice.EXTRA_CLASS,
                new BluetoothClass(Integer.valueOf(deviceProp.mBluetoothClass)));
        intent.putExtra(BluetoothDevice.EXTRA_RSSI, deviceProp.mRssi);
        intent.putExtra(BluetoothDevice.EXTRA_NAME, deviceProp.mName);
        mAdapterService.sendBroadcast(intent, mAdapterService.BLUETOOTH_PERM);

 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

Application broadcast receiving code:

       // Broadcast Register
       private SingBroadcastReceiver mReceiver;
       mReceiver = new SingBroadcastReceiver();
       IntentFilter intentFilter = new IntentFilter();
       intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
       intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
       intentFilter.addAction(BluetoothDevice.ACTION_FOUND);
       registerReceiver(mReceiver, intentFilter);
   <span class="token comment">// Broadcast Receiver</span>
   <span class="token keyword">class</span> <span class="token class-name">SingBroadcastReceiver</span> <span class="token keyword">extends</span> <span class="token class-name">BroadcastReceiver</span> <span class="token punctuation">{<!-- --></span>
       <span class="token annotation punctuation">@Override</span>
       <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">onReceive</span><span class="token punctuation">(</span>Context context<span class="token punctuation">,</span> Intent intent<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
           String action <span class="token operator">=</span> intent<span class="token punctuation">.</span><span class="token function">getAction</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
           <span class="token keyword">if</span> <span class="token punctuation">(</span>BluetoothDevice<span class="token punctuation">.</span>ACTION_FOUND<span class="token punctuation">.</span><span class="token function">equals</span><span class="token punctuation">(</span>action<span class="token punctuation">)</span> <span class="token punctuation">)</span><span class="token punctuation">{<!-- --></span>
               BluetoothDevice device <span class="token operator">=</span> intent<span class="token punctuation">.</span><span class="token function">getParcelableExtra</span><span class="token punctuation">(</span>BluetoothDevice<span class="token punctuation">.</span>EXTRA_DEVICE<span class="token punctuation">)</span><span class="token punctuation">;</span>
               Log<span class="token punctuation">.</span><span class="token function">i</span><span class="token punctuation">(</span><span class="token string">"MainActivity"</span><span class="token punctuation">,</span> <span class="token string">""</span> <span class="token operator">+</span> device<span class="token punctuation">.</span><span class="token function">getName</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token string">" "</span> <span class="token operator">+</span> device<span class="token punctuation">.</span><span class="token function">getAddress</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
           <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>BluetoothDevice<span class="token punctuation">.</span>ACTION_DISCOVERY_STARTED<span class="token punctuation">.</span><span class="token function">equals</span><span class="token punctuation">(</span>action<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">{<!-- --></span>
               Log<span class="token punctuation">.</span><span class="token function">i</span><span class="token punctuation">(</span><span class="token string">"MainActivity"</span><span class="token punctuation">,</span> <span class="token string">"Discovery started."</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
           <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>BluetoothDevice<span class="token punctuation">.</span>ACTION_DISCOVERY_FINISHED<span class="token punctuation">.</span><span class="token function">equals</span><span class="token punctuation">(</span>action<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">{<!-- --></span> 
               Log<span class="token punctuation">.</span><span class="token function">i</span><span class="token punctuation">(</span><span class="token string">"MainActivity"</span><span class="token punctuation">,</span> <span class="token string">"Discovery finished."</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
           <span class="token punctuation">}</span>
       <span class="token punctuation">}</span>
   <span class="token punctuation">}</span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

2)BLE scan

private BluetoothAdapter mBluetoothAdapter;

// Initializes a Bluetooth adapter. For API level 18 and above, get a reference to
// BluetoothAdapter through BluetoothManager.
final BluetoothManager bluetoothManager =
(BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManager.getAdapter();

BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() {
@Override
public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {
Log.i(TAG, "mLeScanCallback device: " + device.getName() + " "+ device.getAddress());
}
};

//Start scan
mBluetoothAdapter.startLeScan(mLeScanCallback);

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

BluetoothAdapter.java (frameworks\base\core\java\android\bluetooth)

    /**
     * Starts a scan for Bluetooth LE devices.
     * @param callback the callback LE scan results are delivered
     */
    @Deprecated
    public boolean startLeScan(LeScanCallback callback) {
        return startLeScan(null, callback);
    }
<span class="token comment">/**
 * Starts a scan for Bluetooth LE devices, looking for devices that
 * advertise given services.
 * @param serviceUuids Array of services to look for
 * @param callback the callback LE scan results are delivered
 */</span>
<span class="token annotation punctuation">@Deprecated</span>
<span class="token keyword">public</span> <span class="token keyword">boolean</span> <span class="token function">startLeScan</span><span class="token punctuation">(</span><span class="token keyword">final</span> UUID<span class="token punctuation">[</span><span class="token punctuation">]</span> serviceUuids<span class="token punctuation">,</span> <span class="token keyword">final</span> LeScanCallback callback<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>DBG<span class="token punctuation">)</span> Log<span class="token punctuation">.</span><span class="token function">d</span><span class="token punctuation">(</span>TAG<span class="token punctuation">,</span> <span class="token string">"startLeScan(): "</span> <span class="token operator">+</span> serviceUuids<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>callback <span class="token operator">==</span> null<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>DBG<span class="token punctuation">)</span> Log<span class="token punctuation">.</span><span class="token function">e</span><span class="token punctuation">(</span>TAG<span class="token punctuation">,</span> <span class="token string">"startLeScan: null callback"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    <span class="token comment">// Get a BluetoothLeScanner object</span>
    BluetoothLeScanner scanner <span class="token operator">=</span> <span class="token function">getBluetoothLeScanner</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>scanner <span class="token operator">==</span> null<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>DBG<span class="token punctuation">)</span> Log<span class="token punctuation">.</span><span class="token function">e</span><span class="token punctuation">(</span>TAG<span class="token punctuation">,</span> <span class="token string">"startLeScan: cannot get BluetoothLeScanner"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
	<span class="token comment">// Judge whether there is a callback for the current scan in mLeScanClients. If yes, it indicates that the scan has started</span>
    <span class="token keyword">synchronized</span><span class="token punctuation">(</span>mLeScanClients<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>mLeScanClients<span class="token punctuation">.</span><span class="token function">containsKey</span><span class="token punctuation">(</span>callback<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
            <span class="token keyword">if</span> <span class="token punctuation">(</span>DBG<span class="token punctuation">)</span> Log<span class="token punctuation">.</span><span class="token function">e</span><span class="token punctuation">(</span>TAG<span class="token punctuation">,</span> <span class="token string">"LE Scan has already started"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>

        <span class="token keyword">try</span> <span class="token punctuation">{<!-- --></span>
       		<span class="token comment">//Get an instance of the BluetoothGatt Binder class, which is defined in GattService.java</span>
       		 <span class="token comment">//GattService internal class private static class bluetoothgattbinder extensions ibluetoothgatt.stub</span>
            IBluetoothGatt iGatt <span class="token operator">=</span> mManagerService<span class="token punctuation">.</span><span class="token function">getBluetoothGatt</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">if</span> <span class="token punctuation">(</span>iGatt <span class="token operator">==</span> null<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
                <span class="token comment">// BLE is not supported</span>
                <span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
            <span class="token punctuation">}</span>
			<span class="token comment">// Scan callback</span>
            ScanCallback scanCallback <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">ScanCallback</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
                <span class="token annotation punctuation">@Override</span>
                <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">onScanResult</span><span class="token punctuation">(</span><span class="token keyword">int</span> callbackType<span class="token punctuation">,</span> ScanResult result<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>

Posted by cjconnor24 on Mon, 29 Nov 2021 08:00:34 -0800