Android蓝牙源码分析——关于GKI
2016-08-19 09:13
495 查看
GKI模块是Bluedroid中用于线程间通信的,我们知道蓝牙所有的操作最终都会交给Bluedroid处理,而调用方可能来自多个线程,Bluedroid中有大量的全局变量,为避免多线程导致的数据不一致问题,干脆统一切换到一个固定的工作线程中执行。类似于Java中的post Runnable,这里是给线程发送消息或事件。
接下来我们开始分析GKI源码,文件并不多,我们首先以gki模块的初始化为入口,在gki_ulinux.c中,如下:
首先将gki_cb清零,这个变量非常重要,如下:
tGKI_OS里有个GKI全局锁,一个线程池,还有关于evt和timeout的锁和条件变量。tGKI_COM_CB作为整个GKI的控制中心,里面的数据结构很复杂。
我们继续回到gki_init,在将gki_cb清零后,接下里先后初始化buffer, timer和alarm_service。然后初始化tGKI_OS中的GKI全局锁,最后创建一个定时器,当定时器到期时内核会启动一个线程执行bt_alarm_cb回调函数。
再来看gki_buffer_init是如何初始化缓冲区的,如下:
GKI缓冲区相关的控制数据结构都在tGKI_COM_CB中,如下:
这里OSTaskQFirst和OSTaskQLast是个BUFFER_HDR_T的二维数组,看上去每个TASK有一个TASK_MBOX数组:
从注释上看每个task有4个mailbox,这个mailbox是用于向task发送buffer的,buffer中可能带了各种参数。
我们回到gki_buffer_init中看是如何初始化buffer的,首先将所有的mailbox都初始化为null,然后gki中一共有GKI_NUM_TOTAL_BUF_POOLS个缓冲池都需要初始化。
再来看gki_timers_init是如何初始化timers的:
timers相比buffer就简单多了,只有三个变量相关,如下:
这里的初始化就是给他们都设为0而已。
再来看看alarm_service_init,如下:
到这里gki初始化完成了,GKI_init是被谁调用的呢?是被bte_main.c中的bte_main_boot_entry调用的,如下:
bte_main_boot_entry又是被谁调用的呢?在btif_core.c的btif_init_bluetooth中,如下:
而btif_init_bluetooth又是被bluetooth.c中init函数调用的,而这个Init又是被谁调用的呢?在Bluetooth.c中如下:
在com_android_bluetooth_btservice_AdapterService.cpp中初始化时有如下代码:
这个sBluetoothInterface就是Bluetooth.c中的&bluetoothInterface,这里面有很多函数指针,当调用init时最终就会走到GKI_init。什么时候调用的呢?在initNative中,如下:
而这个InitNative是AdapterService.java中的native函数,如下:
该函数调用是在AdapterService的onCreate时,如下:
好了,GKI初始化的整个调用路径都搞清楚了,接下来看GKI_create_task是如何创建任务的,如下:
这里会创建一个线程执行gki_task_entry,我们看看这个线程入口函数,如下:
这里prctl用于给线程重命名,然后关键是执行线程的task_entry函数,这个task_entry是GKI_create_task时传入的回调。
我们再来看看哪里调用过了GKI_create_task,主要是两个地方,一个是btif_core.c中的btif_init_bluetooth,另一处是bte_main.c中的bte_main_enable。我们先看btif_init_bluetooth,因为这是初始化后创建的第一个task。
第一个参数是任务的入口函数,第二个是taskid,第三个是task名称,如下:
看来这个btif task是个蓝牙核心线程,如下:
这里在一个无限for循环中用GKI_wait等待事件,当遇到某些事件时break。接下来看看bte_main.c中的bte_main_enable,如下:
原来BTU_TASK是在这里初始化的,看下入口函数btu_task,如下:
这里省略了不少代码,可以看到BTU_TASK远比BTIF_TASK复杂,不过结构都一样,也是在一个loop里不停地GKI_wait获取event,然后处理event。从注释上看BTU是Bluetooth Upper Layers unit的意思。这里我们暂时不去看各种event的处理,只是了解整个底层GKI的架构。
我们注意到这里在进入loop之前做了一些初始化,先看btu_init_core,如下:
再往下看会调GKI_send_event(BTIF_TASK, BT_EVT_TRIGGER_STACK_INIT);向BTIF_TASK发送BT_EVT_TRIGGER_STACK_INIT这个event。我们来看GKI是如何发送消息的,如下:
这里先给目标task的event锁锁上,然后或上该task等待的event,通知该task线程有新的event了,然后解锁返回。我们再看看GKI_wait是如何等待event的:
首先设置OSWaitForEvt,如果设置成0xFFFF就表示所有的事件都要关注,然后锁上thread_evt_mutex,看来这个锁是用来锁OSWaitEvt的,这个是收到的待处理的事件。如果没有事件待处理则清空OSWaitForEvt然后返回。如果有事件,如果需要超时等待,则调用pthread_cond_timedwait,否则调用pthread_cond_wait,则task会阻塞等信号。BTIF TASK和BTU TASK都是不用超时等待的。当有别的线程发event过来时会唤醒当前task,然后从OSWaitEvt中取出要处理的event。
接下来看GKI_send_msg,这和发送event有所区别,如下:
这里每个task都有若干个mailbox,每个mailbox下都有一个buffer队列,这里其实就是发送一个buffer挂载到对应task的对应box下的buffer队列上。然后发送一个事件通知该task有新的message了。
再来看task是如何读取这些message的,在GKI_read_mbox中,如下:
值得注意的是每次发送或者读message都要对GKI全局mutex上锁,完毕后还要释放锁。这里读mbox其实就是从mbox的buffer队列里取下队列头返回。
接下来我们开始分析GKI源码,文件并不多,我们首先以gki模块的初始化为入口,在gki_ulinux.c中,如下:
void GKI_init(void) { pthread_mutexattr_t attr; tGKI_OS *p_os; memset (&gki_cb, 0, sizeof (gki_cb)); gki_buffer_init(); gki_timers_init(); alarm_service_init(); gki_cb.com.OSTicks = (UINT32) times(0); pthread_mutexattr_init(&attr); p_os = &gki_cb.os; pthread_mutex_init(&p_os->GKI_mutex, &attr); struct sigevent sigevent; memset(&sigevent, 0, sizeof(sigevent)); sigevent.sigev_notify = SIGEV_THREAD; sigevent.sigev_notify_function = (void (*)(union sigval))bt_alarm_cb; sigevent.sigev_value.sival_ptr = NULL; if (timer_create(CLOCK_REALTIME, &sigevent, &posix_timer) == -1) { timer_created = false; } else { timer_created = true; } }
首先将gki_cb清零,这个变量非常重要,如下:
tGKI_CB gki_cb; typedef struct { tGKI_OS os; tGKI_COM_CB com; } tGKI_CB; typedef struct { pthread_mutex_t GKI_mutex; pthread_t thread_id[GKI_MAX_TASKS]; pthread_mutex_t thread_evt_mutex[GKI_MAX_TASKS]; pthread_cond_t thread_evt_cond[GKI_MAX_TASKS]; pthread_mutex_t thread_timeout_mutex[GKI_MAX_TASKS]; pthread_cond_t thread_timeout_cond[GKI_MAX_TASKS]; } tGKI_OS; typedef struct { UINT8 *OSStack[GKI_MAX_TASKS]; /* pointer to beginning of stack */ UINT16 OSStackSize[GKI_MAX_TASKS]; /* stack size available to each task */ INT8 *OSTName[GKI_MAX_TASKS]; /* name of the task */ UINT8 OSRdyTbl[GKI_MAX_TASKS]; /* current state of the task */ UINT16 OSWaitEvt[GKI_MAX_TASKS]; /* events that have to be processed by the task */ UINT16 OSWaitForEvt[GKI_MAX_TASKS]; /* events the task is waiting for*/ UINT32 OSTicks; /* system ticks from start */ UINT32 OSIdleCnt; /* idle counter */ INT16 OSDisableNesting; /* counter to keep track of interrupt disable nesting */ INT16 OSLockNesting; /* counter to keep track of sched lock nesting */ INT16 OSIntNesting; /* counter to keep track of interrupt nesting */ /* Timer related variables */ INT32 OSTicksTilExp; /* Number of ticks till next timer expires */ INT32 OSNumOrigTicks; /* Number of ticks between last timer expiration to the next one */ INT32 OSWaitTmr [GKI_MAX_TASKS]; /* ticks the task has to wait, for specific events */ /* Buffer related variables */ BUFFER_HDR_T *OSTaskQFirst[GKI_MAX_TASKS][NUM_TASK_MBOX]; /* array of pointers to the first event in the task mailbox */ BUFFER_HDR_T *OSTaskQLast [GKI_MAX_TASKS][NUM_TASK_MBOX]; /* array of pointers to the last event in the task mailbox */ /* Define the buffer pool management variables */ FREE_QUEUE_T freeq[GKI_NUM_TOTAL_BUF_POOLS]; UINT16 pool_buf_size[GKI_NUM_TOTAL_BUF_POOLS]; UINT16 pool_max_count[GKI_NUM_TOTAL_BUF_POOLS]; UINT16 pool_additions[GKI_NUM_TOTAL_BUF_POOLS]; /* Define the buffer pool start addresses */ UINT8 *pool_start[GKI_NUM_TOTAL_BUF_POOLS]; /* array of pointers to the start of each buffer pool */ UINT8 *pool_end[GKI_NUM_TOTAL_BUF_POOLS]; /* array of pointers to the end of each buffer pool */ UINT16 pool_size[GKI_NUM_TOTAL_BUF_POOLS]; /* actual size of the buffers in a pool */ /* Define the buffer pool access control variables */ void *p_user_mempool; /* User O/S memory pool */ UINT16 pool_access_mask; /* Bits are set if the corresponding buffer pool is a restricted pool */ UINT8 pool_list[GKI_NUM_TOTAL_BUF_POOLS]; /* buffer pools arranged in the order of size */ UINT8 curr_total_no_of_pools; /* number of fixed buf pools + current number of dynamic pools */ BOOLEAN timer_nesting; /* flag to prevent timer interrupt nesting */ } tGKI_COM_CB;
tGKI_OS里有个GKI全局锁,一个线程池,还有关于evt和timeout的锁和条件变量。tGKI_COM_CB作为整个GKI的控制中心,里面的数据结构很复杂。
我们继续回到gki_init,在将gki_cb清零后,接下里先后初始化buffer, timer和alarm_service。然后初始化tGKI_OS中的GKI全局锁,最后创建一个定时器,当定时器到期时内核会启动一个线程执行bt_alarm_cb回调函数。
再来看gki_buffer_init是如何初始化缓冲区的,如下:
void gki_buffer_init(void) { UINT8 i, tt, mb; tGKI_COM_CB *p_cb = &gki_cb.com; /* Initialize mailboxes */ for (tt = 0; tt < GKI_MAX_TASKS; tt++) { for (mb = 0; mb < NUM_TASK_MBOX; mb++) { p_cb->OSTaskQFirst[tt][mb] = NULL; p_cb->OSTaskQLast [tt][mb] = NULL; } } for (tt = 0; tt < GKI_NUM_TOTAL_BUF_POOLS; tt++) { p_cb->pool_start[tt] = NULL; p_cb->pool_end[tt] = NULL; p_cb->pool_size[tt] = 0; p_cb->freeq[tt].p_first = 0; p_cb->freeq[tt].p_last = 0; p_cb->freeq[tt].size = 0; p_cb->freeq[tt].total = 0; p_cb->freeq[tt].cur_cnt = 0; p_cb->freeq[tt].max_cnt = 0; } /* Use default from target.h */ p_cb->pool_access_mask = GKI_DEF_BUFPOOL_PERM_MASK; /* add pools to the pool_list which is arranged in the order of size */ for(i=0; i < GKI_NUM_FIXED_BUF_POOLS ; i++) { p_cb->pool_list[i] = i; } p_cb->curr_total_no_of_pools = GKI_NUM_FIXED_BUF_POOLS; return; }
GKI缓冲区相关的控制数据结构都在tGKI_COM_CB中,如下:
/* Buffer related variables */ BUFFER_HDR_T *OSTaskQFirst[GKI_MAX_TASKS][NUM_TASK_MBOX]; /* array of pointers to the first event in the task mailbox */ BUFFER_HDR_T *OSTaskQLast [GKI_MAX_TASKS][NUM_TASK_MBOX]; /* array of pointers to the last event in the task mailbox */ typedef struct _buffer_hdr { struct _buffer_hdr *p_next; /* next buffer in the queue */ UINT8 q_id; /* id of the queue */ UINT8 task_id; /* task which allocated the buffer*/ UINT8 status; /* FREE, UNLINKED or QUEUED */ UINT8 Type; } BUFFER_HDR_T;
这里OSTaskQFirst和OSTaskQLast是个BUFFER_HDR_T的二维数组,看上去每个TASK有一个TASK_MBOX数组:
#define GKI_MAX_TASKS 3 /************************************************************************ ** 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 #define GKI_NUM_TOTAL_BUF_POOLS 10
从注释上看每个task有4个mailbox,这个mailbox是用于向task发送buffer的,buffer中可能带了各种参数。
我们回到gki_buffer_init中看是如何初始化buffer的,首先将所有的mailbox都初始化为null,然后gki中一共有GKI_NUM_TOTAL_BUF_POOLS个缓冲池都需要初始化。
再来看gki_timers_init是如何初始化timers的:
void gki_timers_init(void) { UINT8 tt; gki_cb.com.OSTicksTilExp = 0; /* Remaining time (of OSTimeCurTimeout) before next timer expires */ gki_cb.com.OSNumOrigTicks = 0; for (tt = 0; tt < GKI_MAX_TASKS; tt++) { gki_cb.com.OSWaitTmr [tt] = 0; } return; }
timers相比buffer就简单多了,只有三个变量相关,如下:
/* Timer related variables */ INT32 OSTicksTilExp; /* Number of ticks till next timer expires */ INT32 OSNumOrigTicks; /* Number of ticks between last timer expiration to the next one */ INT32 OSWaitTmr [GKI_MAX_TASKS]; /* ticks the task has to wait, for specific events */
这里的初始化就是给他们都设为0而已。
再来看看alarm_service_init,如下:
static void alarm_service_init() { alarm_service.ticks_scheduled = 0; alarm_service.timer_started_us = 0; alarm_service.timer_last_expired_us = 0; alarm_service.wakelock = FALSE; raise_priority_a2dp(TASK_JAVA_ALARM); } // Alarm service structure used to pass up via JNI to the bluetooth // app in order to create a wakeable Alarm. typedef struct { UINT32 ticks_scheduled; UINT64 timer_started_us; UINT64 timer_last_expired_us; bool wakelock; } alarm_service_t;
到这里gki初始化完成了,GKI_init是被谁调用的呢?是被bte_main.c中的bte_main_boot_entry调用的,如下:
/****************************************************************************** ** ** Function bte_main_boot_entry ** ** Description BTE MAIN API - Entry point for BTE chip/stack initialization ** ** Returns None ** ******************************************************************************/ void bte_main_boot_entry(void) { /* initialize OS */ GKI_init(); bte_main_in_hw_init(); bte_load_conf(BTE_STACK_CONF_FILE); bte_load_ble_conf(BTE_BLE_STACK_CONF_FILE); pthread_mutex_init(&cleanup_lock, NULL); }
bte_main_boot_entry又是被谁调用的呢?在btif_core.c的btif_init_bluetooth中,如下:
bt_status_t btif_init_bluetooth() { UINT8 status; btif_config_init(); bte_main_boot_entry(); /* As part of the init, fetch the local BD ADDR */ memset(&btif_local_bd_addr, 0, sizeof(bt_bdaddr_t)); btif_fetch_local_bdaddr(&btif_local_bd_addr); /* start btif task */ status = GKI_create_task(btif_task, BTIF_TASK, BTIF_TASK_STR, (UINT16 *) ((UINT8 *)btif_task_stack + BTIF_TASK_STACK_SIZE), sizeof(btif_task_stack)); if (status != GKI_SUCCESS) return BT_STATUS_FAIL; return BT_STATUS_SUCCESS; }
而btif_init_bluetooth又是被bluetooth.c中init函数调用的,而这个Init又是被谁调用的呢?在Bluetooth.c中如下:
static const bt_interface_t bluetoothInterface = { sizeof(bluetoothInterface), init, enable, disable, cleanup, get_adapter_properties, get_adapter_property, set_adapter_property, get_remote_device_properties, get_remote_device_property, set_remote_device_property, get_remote_service_record, get_remote_services, start_discovery, cancel_discovery, create_bond, remove_bond, cancel_bond, get_connection_state, pin_reply, ssp_reply, get_profile_interface, dut_mode_configure, dut_mode_send, #if BLE_INCLUDED == TRUE le_test_mode, #else NULL, #endif config_hci_snoop_log, set_os_callouts, read_energy_info, }; const bt_interface_t* bluetooth__get_bluetooth_interface () { /* fixme -- add property to disable bt interface ? */ return &bluetoothInterface; } static int open_bluetooth_stack (const struct hw_module_t* module, char const* name, struct hw_device_t** abstraction) { UNUSED(name); bluetooth_device_t *stack = malloc(sizeof(bluetooth_device_t) ); memset(stack, 0, sizeof(bluetooth_device_t) ); stack->common.tag = HARDWARE_DEVICE_TAG; stack->common.version = 0; stack->common.module = (struct hw_module_t*)module; stack->common.close = close_bluetooth_stack; stack->get_bluetooth_interface = bluetooth__get_bluetooth_interface; *abstraction = (struct hw_device_t*)stack; return 0; } static struct hw_module_methods_t bt_stack_module_methods = { .open = open_bluetooth_stack, }; struct hw_module_t HAL_MODULE_INFO_SYM = { .tag = HARDWARE_MODULE_TAG, .version_major = 1, .version_minor = 0, .id = BT_HARDWARE_MODULE_ID, .name = "Bluetooth Stack", .author = "The Android Open Source Project", .methods = &bt_stack_module_methods };
在com_android_bluetooth_btservice_AdapterService.cpp中初始化时有如下代码:
const char *id = (strcmp(value, "1")? BT_STACK_MODULE_ID : BT_STACK_TEST_MODULE_ID); 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) { bluetooth_module_t* btStack = (bluetooth_module_t *)abstraction; sBluetoothInterface = btStack->get_bluetooth_interface(); } else { ALOGE("Error while opening Bluetooth library"); } }
这个sBluetoothInterface就是Bluetooth.c中的&bluetoothInterface,这里面有很多函数指针,当调用init时最终就会走到GKI_init。什么时候调用的呢?在initNative中,如下:
static bool initNative(JNIEnv* env, jobject obj) { sJniAdapterServiceObj = env->NewGlobalRef(obj); sJniCallbacksObj = env->NewGlobalRef(env->GetObjectField(obj, sJniCallbacksField)); if (sBluetoothInterface) { int ret = sBluetoothInterface->init(&sBluetoothCallbacks); if (ret != BT_STATUS_SUCCESS) { ALOGE("Error while setting the callbacks: %d\n", ret); sBluetoothInterface = NULL; return JNI_FALSE; } ret = sBluetoothInterface->set_os_callouts(&sBluetoothOsCallouts); if (ret != BT_STATUS_SUCCESS) { ALOGE("Error while setting Bluetooth callouts: %d\n", ret); sBluetoothInterface->cleanup(); sBluetoothInterface = NULL; return JNI_FALSE; } if ( (sBluetoothSocketInterface = (btsock_interface_t *) sBluetoothInterface->get_profile_interface(BT_PROFILE_SOCKETS_ID)) == NULL) { ALOGE("Error getting socket interface"); } return JNI_TRUE; } return JNI_FALSE; }
而这个InitNative是AdapterService.java中的native函数,如下:
private native boolean initNative();
该函数调用是在AdapterService的onCreate时,如下:
@Override public void onCreate() { super.onCreate(); debugLog("onCreate()"); mBinder = new AdapterServiceBinder(this); mAdapterProperties = new AdapterProperties(this); mAdapterStateMachine = AdapterState.make(this, mAdapterProperties); mJniCallbacks = new JniCallbacks(mAdapterStateMachine, mAdapterProperties); initNative(); mNativeAvailable=true; mCallbacks = new RemoteCallbackList<IBluetoothCallback>(); //Load the name and address getAdapterPropertyNative(AbstractionLayer.BT_PROPERTY_BDADDR); getAdapterPropertyNative(AbstractionLayer.BT_PROPERTY_BDNAME); mAlarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE); mPowerManager = (PowerManager) getSystemService(Context.POWER_SERVICE); mSdpManager = SdpManager.init(this); registerReceiver(mAlarmBroadcastReceiver, new IntentFilter(ACTION_ALARM_WAKEUP)); mProfileObserver = new ProfileObserver(getApplicationContext(), this, new Handler()); mProfileObserver.start(); }
好了,GKI初始化的整个调用路径都搞清楚了,接下来看GKI_create_task是如何创建任务的,如下:
UINT8 GKI_create_task (TASKPTR task_entry, UINT8 task_id, INT8 *taskname, UINT16 *stack, UINT16 stacksize) { struct sched_param param; int policy, ret = 0; pthread_attr_t attr1; gki_cb.com.OSRdyTbl[task_id] = TASK_READY; gki_cb.com.OSTName[task_id] = taskname; gki_cb.com.OSWaitTmr[task_id] = 0; gki_cb.com.OSWaitEvt[task_id] = 0; /* Initialize mutex and condition variable objects for events and timeouts */ pthread_condattr_t cond_attr; pthread_condattr_init(&cond_attr); pthread_condattr_setclock(&cond_attr, CLOCK_MONOTONIC); pthread_mutex_init(&gki_cb.os.thread_evt_mutex[task_id], NULL); pthread_cond_init (&gki_cb.os.thread_evt_cond[task_id], &cond_attr); pthread_mutex_init(&gki_cb.os.thread_timeout_mutex[task_id], NULL); pthread_cond_init (&gki_cb.os.thread_timeout_cond[task_id], NULL); /* On Android, the new tasks starts running before 'gki_cb.os.thread_id[task_id]' is initialized */ /* Pass task_id to new task so it can initialize gki_cb.os.thread_id[task_id] for it calls GKI_wait */ gki_pthread_info[task_id].task_id = task_id; gki_pthread_info[task_id].task_entry = task_entry; gki_pthread_info[task_id].params = 0; ret = pthread_create( &gki_cb.os.thread_id[task_id], &attr1, (void *)gki_task_entry, &gki_pthread_info[task_id]); return (GKI_SUCCESS); }
这里会创建一个线程执行gki_task_entry,我们看看这个线程入口函数,如下:
static void gki_task_entry(UINT32 params) { gki_pthread_info_t *p_pthread_info = (gki_pthread_info_t *)params; gki_cb.os.thread_id[p_pthread_info->task_id] = pthread_self(); prctl(PR_SET_NAME, (unsigned long)gki_cb.com.OSTName[p_pthread_info->task_id], 0, 0, 0); /* Call the actual thread entry point */ (p_pthread_info->task_entry)(p_pthread_info->params); pthread_exit(0); /* GKI tasks have no return value */ }
这里prctl用于给线程重命名,然后关键是执行线程的task_entry函数,这个task_entry是GKI_create_task时传入的回调。
我们再来看看哪里调用过了GKI_create_task,主要是两个地方,一个是btif_core.c中的btif_init_bluetooth,另一处是bte_main.c中的bte_main_enable。我们先看btif_init_bluetooth,因为这是初始化后创建的第一个task。
/* start btif task */ status = GKI_create_task(btif_task, BTIF_TASK, BTIF_TASK_STR, (UINT16 *) ((UINT8 *)btif_task_stack + BTIF_TASK_STACK_SIZE), sizeof(btif_task_stack));
第一个参数是任务的入口函数,第二个是taskid,第三个是task名称,如下:
#define BTIF_TASK_STR ((INT8 *) "BTIF") #define BTU_TASK 0 #define BTIF_TASK 1 #define A2DP_MEDIA_TASK 2
看来这个btif task是个蓝牙核心线程,如下:
static void btif_task(UINT32 params) { UINT16 event; BT_HDR *p_msg; btif_associate_evt(); for(;;) { /* wait for specified events */ event = GKI_wait(0xFFFF, 0); /* * Wait for the trigger to init chip and stack. This trigger will * be received by btu_task once the UART is opened and ready */ if (event == BT_EVT_TRIGGER_STACK_INIT) { #if (BLE_INCLUDED == TRUE) btif_dm_load_ble_local_keys(); #endif BTA_EnableBluetooth(bte_dm_evt); } /* * Failed to initialize controller hardware, reset state and bring * down all threads */ if (event == BT_EVT_HARDWARE_INIT_FAIL) { bte_main_disable(); btif_queue_release(); GKI_task_self_cleanup(BTIF_TASK); bte_main_shutdown(); btif_dut_mode = 0; btif_core_state = BTIF_CORE_STATE_DISABLED; HAL_CBACK(bt_hal_cbacks,adapter_state_changed_cb,BT_STATE_OFF); break; } if (event & EVENT_MASK(GKI_SHUTDOWN_EVT)) break; if(event & TASK_MBOX_1_EVT_MASK) { while((p_msg = GKI_read_mbox(BTU_BTIF_MBOX)) != NULL) { switch (p_msg->event) { case BT_EVT_CONTEXT_SWITCH_EVT: btif_context_switched(p_msg); break; default: BTIF_TRACE_ERROR("unhandled btif event (%d)", p_msg->event & BT_EVT_MASK); break; } GKI_freebuf(p_msg); } } } btif_disassociate_evt(); }
这里在一个无限for循环中用GKI_wait等待事件,当遇到某些事件时break。接下来看看bte_main.c中的bte_main_enable,如下:
void bte_main_enable() { /* Initialize BTE control block */ BTE_Init(); lpm_enabled = FALSE; GKI_create_task((TASKPTR)btu_task, BTU_TASK, BTE_BTU_TASK_STR, (UINT16 *) ((UINT8 *)bte_btu_stack + BTE_BTU_STACK_SIZE), sizeof(bte_btu_stack)); bte_hci_enable(); GKI_run(); }
原来BTU_TASK是在这里初始化的,看下入口函数btu_task,如下:
/******************************************************************************* ** ** 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; /* Initialize the mandatory core stack control blocks (BTU, BTM, L2CAP, and SDP) */ btu_init_core(); /* Initialize any optional stack components */ BTE_InitStack(); bta_sys_init(); /* Send a startup evt message to BTIF_TASK to kickstart the init procedure */ GKI_send_event(BTIF_TASK, BT_EVT_TRIGGER_STACK_INIT); prctl(PR_SET_NAME, (unsigned long)"BTU TASK", 0, 0, 0); raise_priority_a2dp(TASK_HIGH_BTU); /* Wait for, and process, events */ for (;;) { event = GKI_wait (0xFFFF, 0); if (event & TASK_MBOX_0_EVT_MASK) { /* Process all messages in the queue */ while ((p_msg = (BT_HDR *) GKI_read_mbox (BTU_HCI_RCV_MBOX)) != NULL) { /* Determine the input message type. */ switch (p_msg->event & BT_EVT_MASK) { } } } } return(0); }
这里省略了不少代码,可以看到BTU_TASK远比BTIF_TASK复杂,不过结构都一样,也是在一个loop里不停地GKI_wait获取event,然后处理event。从注释上看BTU是Bluetooth Upper Layers unit的意思。这里我们暂时不去看各种event的处理,只是了解整个底层GKI的架构。
我们注意到这里在进入loop之前做了一些初始化,先看btu_init_core,如下:
void btu_init_core(void) { /* Initialize the mandatory core stack components */ btm_init(); l2c_init(); sdp_init(); #if BLE_INCLUDED == TRUE gatt_init(); #if (defined(SMP_INCLUDED) && SMP_INCLUDED == TRUE) SMP_Init(); #endif btm_ble_init(); #endif }
再往下看会调GKI_send_event(BTIF_TASK, BT_EVT_TRIGGER_STACK_INIT);向BTIF_TASK发送BT_EVT_TRIGGER_STACK_INIT这个event。我们来看GKI是如何发送消息的,如下:
/******************************************************************************* ** ** Function GKI_send_event ** ** Description This function is called by tasks to send events to other ** tasks. Tasks can also send events to themselves. ** ** Parameters: task_id - (input) The id of the task to which the event has to ** be sent ** event - (input) The event that has to be sent ** ** ** Returns GKI_SUCCESS if all OK, else GKI_FAILURE ** *******************************************************************************/ UINT8 GKI_send_event (UINT8 task_id, UINT16 event) { if (task_id < GKI_MAX_TASKS) { /* protect OSWaitEvt[task_id] from manipulation in GKI_wait() */ pthread_mutex_lock(&gki_cb.os.thread_evt_mutex[task_id]); /* Set the event bit */ gki_cb.com.OSWaitEvt[task_id] |= event; pthread_cond_signal(&gki_cb.os.thread_evt_cond[task_id]); pthread_mutex_unlock(&gki_cb.os.thread_evt_mutex[task_id]); return ( GKI_SUCCESS ); } return (GKI_FAILURE); }
这里先给目标task的event锁锁上,然后或上该task等待的event,通知该task线程有新的event了,然后解锁返回。我们再看看GKI_wait是如何等待event的:
/******************************************************************************* ** ** Function GKI_wait ** ** Description This function is called by tasks to wait for a specific ** event or set of events. The task may specify the duration ** that it wants to wait for, or 0 if infinite. ** ** Parameters: flag - (input) the event or set of events to wait for ** timeout - (input) the duration that the task wants to wait ** for the specific events (in system ticks) ** ** ** Returns the event mask of received events or zero if timeout ** *******************************************************************************/ UINT16 GKI_wait (UINT16 flag, UINT32 timeout) { UINT16 evt; UINT8 rtask; struct timespec abstime = { 0, 0 }; int sec; int nano_sec; rtask = GKI_get_taskid(); gki_cb.com.OSWaitForEvt[rtask] = flag; /* protect OSWaitEvt[rtask] from modification from an other thread */ pthread_mutex_lock(&gki_cb.os.thread_evt_mutex[rtask]); if (!(gki_cb.com.OSWaitEvt[rtask] & flag)) { if (timeout) { clock_gettime(CLOCK_MONOTONIC, &abstime); /* add timeout */ sec = timeout / 1000; nano_sec = (timeout % 1000) * NANOSEC_PER_MILLISEC; abstime.tv_nsec += nano_sec; if (abstime.tv_nsec > NSEC_PER_SEC) { abstime.tv_sec += (abstime.tv_nsec / NSEC_PER_SEC); abstime.tv_nsec = abstime.tv_nsec % NSEC_PER_SEC; } abstime.tv_sec += sec; pthread_cond_timedwait(&gki_cb.os.thread_evt_cond[rtask], &gki_cb.os.thread_evt_mutex[rtask], &abstime); } else { pthread_cond_wait(&gki_cb.os.thread_evt_cond[rtask], &gki_cb.os.thread_evt_mutex[rtask]); } /* TODO: check, this is probably neither not needed depending on phtread_cond_wait() implmentation, e.g. it looks like it is implemented as a counter in which case multiple cond_signal should NOT be lost! */ /* we are waking up after waiting for some events, so refresh variables no need to call GKI_disable() here as we know that we will have some events as we've been waking up after condition pending or timeout */ if (gki_cb.com.OSTaskQFirst[rtask][0]) gki_cb.com.OSWaitEvt[rtask] |= TASK_MBOX_0_EVT_MASK; if (gki_cb.com.OSTaskQFirst[rtask][1]) gki_cb.com.OSWaitEvt[rtask] |= TASK_MBOX_1_EVT_MASK; if (gki_cb.com.OSTaskQFirst[rtask][2]) gki_cb.com.OSWaitEvt[rtask] |= TASK_MBOX_2_EVT_MASK; if (gki_cb.com.OSTaskQFirst[rtask][3]) gki_cb.com.OSWaitEvt[rtask] |= TASK_MBOX_3_EVT_MASK; if (gki_cb.com.OSRdyTbl[rtask] == TASK_DEAD) { gki_cb.com.OSWaitEvt[rtask] = 0; /* unlock thread_evt_mutex as pthread_cond_wait() does auto lock when cond is met */ pthread_mutex_unlock(&gki_cb.os.thread_evt_mutex[rtask]); return (EVENT_MASK(GKI_SHUTDOWN_EVT)); } } /* Clear the wait for event mask */ gki_cb.com.OSWaitForEvt[rtask] = 0; /* Return only those bits which user wants... */ evt = gki_cb.com.OSWaitEvt[rtask] & flag; /* Clear only those bits which user wants... */ gki_cb.com.OSWaitEvt[rtask] &= ~flag; /* unlock thread_evt_mutex as pthread_cond_wait() does auto lock mutex when cond is met */ pthread_mutex_unlock(&gki_cb.os.thread_evt_mutex[rtask]); GKI_TRACE("GKI_wait %d %x %d %x done", (int)rtask, (int)flag, (int)timeout, (int)evt); return (evt); }
首先设置OSWaitForEvt,如果设置成0xFFFF就表示所有的事件都要关注,然后锁上thread_evt_mutex,看来这个锁是用来锁OSWaitEvt的,这个是收到的待处理的事件。如果没有事件待处理则清空OSWaitForEvt然后返回。如果有事件,如果需要超时等待,则调用pthread_cond_timedwait,否则调用pthread_cond_wait,则task会阻塞等信号。BTIF TASK和BTU TASK都是不用超时等待的。当有别的线程发event过来时会唤醒当前task,然后从OSWaitEvt中取出要处理的event。
接下来看GKI_send_msg,这和发送event有所区别,如下:
void GKI_send_msg (UINT8 task_id, UINT8 mbox, void *msg) { BUFFER_HDR_T *p_hdr; tGKI_COM_CB *p_cb = &gki_cb.com; p_hdr = (BUFFER_HDR_T *) ((UINT8 *) msg - BUFFER_HDR_SIZE); GKI_disable(); if (p_cb->OSTaskQFirst[task_id][mbox]) p_cb->OSTaskQLast[task_id][mbox]->p_next = p_hdr; else p_cb->OSTaskQFirst[task_id][mbox] = p_hdr; p_cb->OSTaskQLast[task_id][mbox] = p_hdr; p_hdr->p_next = NULL; p_hdr->status = BUF_STATUS_QUEUED; p_hdr->task_id = task_id; GKI_enable(); GKI_send_event(task_id, (UINT16)EVENT_MASK(mbox)); return; }
这里每个task都有若干个mailbox,每个mailbox下都有一个buffer队列,这里其实就是发送一个buffer挂载到对应task的对应box下的buffer队列上。然后发送一个事件通知该task有新的message了。
再来看task是如何读取这些message的,在GKI_read_mbox中,如下:
void *GKI_read_mbox (UINT8 mbox) { UINT8 task_id = GKI_get_taskid(); void *p_buf = NULL; BUFFER_HDR_T *p_hdr; GKI_disable(); if (gki_cb.com.OSTaskQFirst[task_id][mbox]) { p_hdr = gki_cb.com.OSTaskQFirst[task_id][mbox]; gki_cb.com.OSTaskQFirst[task_id][mbox] = p_hdr->p_next; p_hdr->p_next = NULL; p_hdr->status = BUF_STATUS_UNLINKED; p_buf = (UINT8 *)p_hdr + BUFFER_HDR_SIZE; } GKI_enable(); return (p_buf); }
值得注意的是每次发送或者读message都要对GKI全局mutex上锁,完毕后还要释放锁。这里读mbox其实就是从mbox的buffer队列里取下队列头返回。
相关文章推荐
- Android蓝牙源码分析——GKI定时器
- [Android源码分析]蓝牙打开分析--苦尽甘来之再次回到jni之上
- [Android源码分析]蓝牙配对之jni之上的点点滴滴
- Android4.42-Settings源码分析之蓝牙模块Bluetooth整体实现(总)
- Android蓝牙源码分析——Gatt的Connection ID
- 关于Android 电话接通的时候,将proximity sensor开启的源码分析
- Android菜鸟开发之蓝牙(Bluetooth)---设置应用源码分析
- Android中从源码分析关于AsyncTask的使用
- Android蓝牙源码分析——Gatt连接(一)
- 蓝牙文件传输之obex层之上的分析【Android源码解析】
- Android蓝牙源码分析——Gatt写设备
- [Android源码分析]蓝牙打开流程分析——jni层之上的方方面面
- [Android源码解析]蓝牙扫描结果反馈的分析
- Android4.42-Setting源码分析之蓝牙模块Bluetooth(下)
- Android源码分析系列-整理篇 ------ 关于Vold 自动挂载部分
- [Android源码分析]蓝牙打开流程分析——jni层之下的偷偷摸摸(Service Record的创建)
- android 蓝牙源码分析
- [Android源码分析]蓝牙文件传输过程解析之UI实现
- Android蓝牙源码分析——BTA层消息分发
- Android蓝牙源码分析——StateMachine状态机