注:基于mtk平台的android6.0,由于我个人水平有限,代码细节不能详细说明,抱歉

参考文章:

http://blog.csdn.net/shichaog/article/details/52728684

http://blog.csdn.net/baimy1985/article/details/8922508
http://blog.csdn.net/yanli0084/article/details/51821064
谢谢以上大佬

首先从BluetoothAdapter.enable开始

frameworks/base/core/java/android/bluetooth.BluetoothAdapter.java public boolean enable() {int state = STATE_OFF;if (isEnabled() == true){if (DBG) Log.d(TAG, "enable(): BT is already enabled..!");return true;}//Use service interface to get the exact stateif (mService != null) {try {state = mService.getState();} catch (RemoteException e) {Log.e(TAG, "", e);}}if (state == BluetoothAdapter.STATE_BLE_ON) {Log.e(TAG, "BT is in BLE_ON State");notifyUserAction(true);return true;}try {if (DBG) Log.d(TAG, "enable");return mManagerService.enable();} catch (RemoteException e) {Log.e(TAG, "", e);}return false;}

这个mManagerService是构造函数传来的,再看看单例的getDefaultAdapter

    public static synchronized BluetoothAdapter getDefaultAdapter() {if (sAdapter == null) {IBinder b = ServiceManager.getService(BLUETOOTH_MANAGER_SERVICE);if (b != null) {IBluetoothManager managerService = IBluetoothManager.Stub.asInterface(b);sAdapter = new BluetoothAdapter(managerService);} else {Log.e(TAG, "Bluetooth binder is null");}}return sAdapter;}

看来有个地方把binder注册成了BLUETOOTH_MANAGER_SERVICE,搜索发现在BluetoothService中

    @Overridepublic void onStart() {Log.d(TAG, "onStart: publishing BluetoothManagerService");publishBinderService(BluetoothAdapter.BLUETOOTH_MANAGER_SERVICE, mBluetoothManagerService);}

这个mBluetoothManagerService是BluetoothManagerService.java的实例。

    public boolean enable() {if ((Binder.getCallingUid() != Process.SYSTEM_UID) &&(!checkIfCallerIsForegroundUser())) {Log.w(TAG,"enable(): not allowed for non-active and non system user");return false;}mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,"Need BLUETOOTH ADMIN permission");if (DBG) {Log.d(TAG,"enable():  mBluetooth =" + mBluetooth +" mBinding = " + mBinding);}/// M: MoMS permission check @{if (MobileManagerUtils.isSupported()) {checkEnablePermission();return true;}/// @}synchronized(mReceiver) {mQuietEnableExternal = false;mEnableExternal = true;// waive WRITE_SECURE_SETTINGS permission checksendEnableMsg(false);}if (DBG) Log.d(TAG, "enable returning");return true;}
    private void sendEnableMsg(boolean quietMode) {mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_ENABLE,quietMode ? 1 : 0, 0));}
              case MESSAGE_ENABLE:if (DBG) {Log.d(TAG, "MESSAGE_ENABLE: mBluetooth = " + mBluetooth);}mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE);mEnable = true;handleEnable(msg.arg1 == 1);break;
    private void handleEnable(boolean quietMode) {mQuietEnable = quietMode;synchronized(mConnection) {if (DBG) Log.d(TAG, "handleEnable: mBluetooth = " + mBluetooth +", mBinding = " + mBinding + "quietMode = " + quietMode);if ((mBluetooth == null) && (!mBinding)) {if (DBG) Log.d(TAG, "Bind AdapterService");//Start bind timeout and bindMessage timeoutMsg=mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND);mHandler.sendMessageDelayed(timeoutMsg,TIMEOUT_BIND_MS);mConnection.setGetNameAddressOnly(false);Intent i = new Intent(IBluetooth.class.getName());if (!doBind(i, mConnection,Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT,UserHandle.CURRENT)) {mHandler.removeMessages(MESSAGE_TIMEOUT_BIND);Log.e(TAG, "Fail to bind to: " + IBluetooth.class.getName());} else {mBinding = true;}} else if (mBluetooth != null) {if (mConnection.isGetNameAddressOnly()) {// if GetNameAddressOnly is set, we can clear this flag,// so the service won't be unbind// after name and address are savedmConnection.setGetNameAddressOnly(false);//Register callback objecttry {mBluetooth.registerCallback(mBluetoothCallback);} catch (RemoteException re) {Log.e(TAG, "Unable to register BluetoothCallback",re);}//Inform BluetoothAdapter instances that service is upsendBluetoothServiceUpCallback();}//Enable bluetoothtry {if (!mQuietEnable) {if(!mBluetooth.enable()) {Log.e(TAG,"IBluetooth.enable() returned false");}}else {if(!mBluetooth.enableNoAutoConnect()) {Log.e(TAG,"IBluetooth.enableNoAutoConnect() returned false");}}} catch (RemoteException e) {Log.e(TAG,"Unable to call enable()",e);}}}}
    boolean doBind(Intent intent, ServiceConnection conn, int flags, UserHandle user) {ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);intent.setComponent(comp);if (comp == null || !mContext.bindServiceAsUser(intent, conn, flags, user)) {Log.e(TAG, "Fail to bind to: " + intent);return false;}return true;}

这个intent指向packages/apps/Bluetooth的AdapterService

Manifest.xml<serviceandroid:process="@string/process"android:name = ".btservice.AdapterService"><intent-filter><action android:name="android.bluetooth.IBluetooth" /></intent-filter></service>

bindService的时候注意看这个mConnection,它是BluetoothServiceConnection的实例,在onServiceConnected里

        public void onServiceConnected(ComponentName className, IBinder service) {if (DBG) Log.d(TAG, "BluetoothServiceConnection: " + className.getClassName());Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_CONNECTED);// TBD if (className.getClassName().equals(IBluetooth.class.getName())) {if (className.getClassName().equals("com.android.bluetooth.btservice.AdapterService")) {msg.arg1 = SERVICE_IBLUETOOTH;// } else if (className.getClassName().equals(IBluetoothGatt.class.getName())) {} else if (className.getClassName().equals("com.android.bluetooth.gatt.GattService")) {msg.arg1 = SERVICE_IBLUETOOTHGATT;} else {Log.e(TAG, "Unknown service connected: " + className.getClassName());return;}msg.obj = service;mHandler.sendMessage(msg);}
                case MESSAGE_BLUETOOTH_SERVICE_CONNECTED:{if (DBG) Log.d(TAG,"MESSAGE_BLUETOOTH_SERVICE_CONNECTED: " + msg.arg1);IBinder service = (IBinder) msg.obj;synchronized(mConnection) {if (msg.arg1 == SERVICE_IBLUETOOTHGATT) {mBluetoothGatt = IBluetoothGatt.Stub.asInterface(service);onBluetoothGattServiceUp();break;} // else must be SERVICE_IBLUETOOTH//Remove timeoutmHandler.removeMessages(MESSAGE_TIMEOUT_BIND);mBinding = false;mBluetooth = IBluetooth.Stub.asInterface(service);try {boolean enableHciSnoopLog = (Settings.Secure.getInt(mContentResolver,Settings.Secure.BLUETOOTH_HCI_LOG, 0) == 1);if (!mBluetooth.configHciSnoopLog(enableHciSnoopLog)) {Log.e(TAG,"IBluetooth.configHciSnoopLog return false");}} catch (RemoteException e) {Log.e(TAG,"Unable to call configHciSnoopLog", e);}if (mConnection.isGetNameAddressOnly()) {//Request GET NAME AND ADDRESSMessage getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS);mHandler.sendMessage(getMsg);if (!mEnable) return;}mConnection.setGetNameAddressOnly(false);//Register callback objecttry {mBluetooth.registerCallback(mBluetoothCallback);} catch (RemoteException re) {Log.e(TAG, "Unable to register BluetoothCallback",re);}//Inform BluetoothAdapter instances that service is upsendBluetoothServiceUpCallback();//Do enable requesttry {if (mQuietEnable == false) {if(!mBluetooth.enable()) {Log.e(TAG,"IBluetooth.enable() returned false");}}else{if(!mBluetooth.enableNoAutoConnect()) {Log.e(TAG,"IBluetooth.enableNoAutoConnect() returned false");}}} catch (RemoteException e) {Log.e(TAG,"Unable to call enable()",e);}}if (!mEnable) {waitForOnOff(true, false);handleDisable();waitForOnOff(false, false);}break;}

看到没,刚才mBluetooth 为空才去bindService,这个bind完成也要调用mBluetooth.enable()

在AdapterService的onBind会返回AdapterServiceBinder,看下AdapterServiceBinder

        public boolean enable() {if ((Binder.getCallingUid() != Process.SYSTEM_UID) &&(!Utils.checkCaller())) {Log.w(TAG, "enable() - Not allowed for non-active user and non system user");return false;}AdapterService service = getService();if (service == null) return false;return service.enable();}

最终调用AdapterService的enable()

AdapterServicepublic synchronized boolean enable(boolean quietMode) {enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission");debugLog("enable() - Enable called with quiet mode status =  " + mQuietmode);mQuietmode = quietMode;Message m = mAdapterStateMachine.obtainMessage(AdapterState.BLE_TURN_ON);mAdapterStateMachine.sendMessage(m);return true;}

这里和android4.2的不太一样,打开了ble?先不管这个。看看AdapterState内部类OffState的处理

            switch(msg.what) {case BLE_TURN_ON:notifyAdapterStateChange(BluetoothAdapter.STATE_BLE_TURNING_ON);mPendingCommandState.setBleTurningOn(true);transitionTo(mPendingCommandState);sendMessageDelayed(BLE_START_TIMEOUT, BLE_START_TIMEOUT_DELAY);adapterService.BleOnProcessStart();break;
AdapterService.javavoid BleOnProcessStart() {debugLog("BleOnProcessStart()");Class[] supportedProfileServices = Config.getSupportedProfiles();//Initialize data objectsdebugLog("supportedProfileServices.length = " + supportedProfileServices.length);for (int i=0; i < supportedProfileServices.length;i++) {debugLog("supportedProfileServices[" + i + "]: " + supportedProfileServices[i].getName());mProfileServicesState.put(supportedProfileServices[i].getName(),BluetoothAdapter.STATE_OFF);}mRemoteDevices = new RemoteDevices(this);mAdapterProperties.init(mRemoteDevices);debugLog("BleOnProcessStart() - Make Bond State Machine");mBondStateMachine = BondStateMachine.make(this, mAdapterProperties, mRemoteDevices);mJniCallbacks.init(mBondStateMachine,mRemoteDevices);//FIXME: Set static instance here???setAdapterService(this);//Start Gatt servicesetGattProfileServiceState(supportedProfileServices,BluetoothAdapter.STATE_ON);}

这个把声明支持的profile加载进来,具体不分析了,只上xml配置

config.xml
<resources><bool name="profile_supported_a2dp">true</bool><bool name="profile_supported_a2dp_sink">false</bool><bool name="profile_supported_hdp">true</bool><bool name="profile_supported_hs_hfp">true</bool><bool name="profile_supported_hfpclient">false</bool><bool name="profile_supported_hid">true</bool><bool name="profile_supported_opp">true</bool><bool name="profile_supported_pan">true</bool><bool name="profile_supported_pbap">true</bool><bool name="profile_supported_gatt">true</bool><bool name="pbap_include_photos_in_vcard">false</bool><bool name="pbap_use_profile_for_owner_vcard">true</bool><bool name="profile_supported_map">true</bool><bool name="profile_supported_avrcp_controller">false</bool><bool name="profile_supported_sap">false</bool>

再看看setGattProfileServiceState

AdapterService.javaprivate void setGattProfileServiceState(Class[] services, int state) {if (state != BluetoothAdapter.STATE_ON && state != BluetoothAdapter.STATE_OFF) {Log.w(TAG,"setGattProfileServiceState(): invalid state...Leaving...");return;}int expectedCurrentState= BluetoothAdapter.STATE_OFF;int pendingState = BluetoothAdapter.STATE_TURNING_ON;if (state == BluetoothAdapter.STATE_OFF) {expectedCurrentState= BluetoothAdapter.STATE_ON;pendingState = BluetoothAdapter.STATE_TURNING_OFF;}for (int i=0; i <services.length;i++) {String serviceName = services[i].getName();String simpleName = services[i].getSimpleName();if (simpleName.equals("GattService")) {Integer serviceState = mProfileServicesState.get(serviceName);if(serviceState != null && serviceState != expectedCurrentState) {debugLog("setProfileServiceState() - Unable to "+ (state == BluetoothAdapter.STATE_OFF ? "start" : "stop" )+ " service " + serviceName+ ". Invalid state: " + serviceState);continue;}debugLog("setProfileServiceState() - "+ (state == BluetoothAdapter.STATE_OFF ? "Stopping" : "Starting")+ " service " + serviceName);mProfileServicesState.put(serviceName,pendingState);Intent intent = new Intent(this,services[i]);intent.putExtra(EXTRA_ACTION,ACTION_SERVICE_STATE_CHANGED);intent.putExtra(BluetoothAdapter.EXTRA_STATE,state);startService(intent);return;}}}

打开了GattService.java,GattService继承了ProfileService,在ProfileService的onStartCommand中

调用了notifyProfileServiceStateChanged(BluetoothAdapter.STATE_ON);

    protected void notifyProfileServiceStateChanged(int state) {//Notify adapter serviceif (mAdapterService != null) {mAdapterService.onProfileServiceStateChanged(getClass().getName(), state);}}
AdapterService.javapublic void onProfileServiceStateChanged(String serviceName, int state) {Message m = mHandler.obtainMessage(MESSAGE_PROFILE_SERVICE_STATE_CHANGED);m.obj=serviceName;m.arg1 = state;mHandler.sendMessage(m);}
            switch (msg.what) {case MESSAGE_PROFILE_SERVICE_STATE_CHANGED: {debugLog("handleMessage() - MESSAGE_PROFILE_SERVICE_STATE_CHANGED");processProfileServiceStateChanged((String) msg.obj, msg.arg1);}break;
    private void processProfileServiceStateChanged(String serviceName, int state) {
...if (isBleTurningOn) {if (serviceName.equals("com.android.bluetooth.gatt.GattService")) {debugLog("GattService is started");mAdapterStateMachine.sendMessage(mAdapterStateMachine.obtainMessage(AdapterState.BLE_STARTED));return;}} 

还是在OffState中

                case BLE_STARTED://Remove start timeoutremoveMessages(BLE_START_TIMEOUT);//Enableboolean isGuest = UserManager.get(mAdapterService).isGuestUser();if (!adapterService.enableNative(isGuest)) {errorLog("Error while turning Bluetooth on");notifyAdapterStateChange(BluetoothAdapter.STATE_OFF);transitionTo(mOffState);} else {sendMessageDelayed(ENABLE_TIMEOUT, ENABLE_TIMEOUT_DELAY);}break;

调用了AdapterService的enableNative方法,这是个jni调用,在com_android_bluetooth_btservice_AdapterService.cpp中声明了该方法

static jboolean enableNative(JNIEnv* env, jobject obj, jboolean isGuest) {ALOGV("%s:",__FUNCTION__);jboolean result = JNI_FALSE;if (!sBluetoothInterface) return result;int ret = sBluetoothInterface->enable(isGuest == JNI_TRUE ? 1 : 0);result = (ret == BT_STATUS_SUCCESS || ret == BT_STATUS_DONE) ? JNI_TRUE : JNI_FALSE;return result;
}

调用了sBluetoothInterface->enable,这个 sBluetoothInterface在classInitNative中初始化了

static void classInitNative(JNIEnv* env, jclass clazz) {int err;hw_module_t* module;
...char value[PROPERTY_VALUE_MAX];property_get("bluetooth.mock_stack", value, "");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");}} else {ALOGE("No Bluetooth Library found");}

hw_get_module是定义在hardware/libhardware/Hardware.c中的方法,jni文件的.mk中声明了LOCAL_SHARED_LIBRARIES+=libhardware,所以ok

int hw_get_module(const char *id, const struct hw_module_t **module)
{return hw_get_module_by_class(id, NULL, module);
}
static int hw_module_exists(char *path, size_t path_len, const char *name,const char *subname)
{
...return load(class_id, path, module);
}
static int load(const char *id,const char *path,const struct hw_module_t **pHmi)
{int status = -EINVAL;void *handle = NULL;struct hw_module_t *hmi = NULL;/** load the symbols resolving undefined symbols before* dlopen returns. Since RTLD_GLOBAL is not or'd in with* RTLD_NOW the external symbols will not be global*/handle = dlopen(path, RTLD_NOW);if (handle == NULL) {char const *err_str = dlerror();ALOGE("load: module=%s\n%s", path, err_str?err_str:"unknown");status = -EINVAL;goto done;}/* 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);if (hmi == NULL) {ALOGE("load: couldn't find symbol %s", sym);status = -EINVAL;goto done;}/* Check that the id matches */if (strcmp(id, hmi->id) != 0) {ALOGE("load: id=%s != hmi->id=%s", id, hmi->id);status = -EINVAL;goto done;}hmi->dso = handle;/* success */status = 0;done:if (status != 0) {hmi = NULL;if (handle != NULL) {dlclose(handle);handle = NULL;}} else {ALOGV("loaded HAL id=%s path=%s hmi=%p handle=%p",id, path, *pHmi, handle);}*pHmi = hmi;return status;
}

这段代码不太懂,感觉就是打开一个c文件,传入id是BT_STACK_MODULE_ID,因为const char *id = (strcmp(value, "1")? BT_STACK_MODULE_ID : BT_STACK_TEST_MODULE_ID);后面那个明显是test的啊

至于BT_STACK_MODULE_ID,在hardware/libhardware/include/hardware/Bluetooth.h中定义了

#define BT_STACK_MODULE_ID "bluetooth"

看下system/bt/btif/src/Bluetooth.c,果然找到相关方法

const bt_interface_t* bluetooth__get_bluetooth_interface ()
{/* fixme -- add property to disable bt interface ? */return &bluetoothInterface;
}
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 == TRUEle_test_mode,
#elseNULL,
#endifconfig_hci_snoop_log,set_os_callouts,read_energy_info,dump,config_clear
};
static int enable(bool start_restricted) {LOG_INFO(LOG_TAG, "%s: start restricted = %d", __func__, start_restricted);restricted_mode = start_restricted;if (!interface_ready())return BT_STATUS_NOT_READY;stack_manager_get_interface()->start_up_stack_async();return BT_STATUS_SUCCESS;
}

stack_manager_get_interface在stack_manager.c中

const stack_manager_t *stack_manager_get_interface() {ensure_manager_initialized();return &interface;
}
static const stack_manager_t interface = {init_stack,start_up_stack_async,shut_down_stack_async,clean_up_stack_async,get_stack_is_running
};
static void start_up_stack_async(void) {thread_post(management_thread, event_start_up_stack, NULL);
}
static void event_start_up_stack(UNUSED_ATTR void *context) {if (stack_is_running) {LOG_DEBUG("%s stack already brought up.", __func__);return;}ensure_stack_is_initialized();LOG_DEBUG("%s is bringing up the stack.", __func__);hack_future = future_new();// Include this for now to put btif config into a shutdown-able statemodule_start_up(get_module(BTIF_CONFIG_MODULE));bte_main_enable();if (future_await(hack_future) != FUTURE_SUCCESS) {stack_is_running = true; // So stack shutdown actually happensevent_shut_down_stack(NULL);return; }  stack_is_running = true;  LOG_DEBUG("%s finished", __func__);    btif_thread_post(event_signal_stack_up, NULL);}

Bte_main.c

void bte_main_enable()
{APPL_TRACE_DEBUG("%s", __FUNCTION__);module_start_up(get_module(BTSNOOP_MODULE));module_start_up(get_module(HCI_MODULE));BTU_StartUp();
}

Btu_init.c

void BTU_StartUp(void)
{memset (&btu_cb, 0, sizeof (tBTU_CB));btu_cb.trace_level = HCI_INITIAL_TRACE_LEVEL;btu_bta_msg_queue = fixed_queue_new(SIZE_MAX);if (btu_bta_msg_queue == NULL)goto error_exit;btu_general_alarm_hash_map = hash_map_new(BTU_GENERAL_ALARM_HASH_MAP_SIZE,hash_function_pointer, NULL, (data_free_fn)alarm_free, NULL);if (btu_general_alarm_hash_map == NULL)goto error_exit;if (pthread_mutex_init(&btu_general_alarm_lock, NULL))goto error_exit;btu_general_alarm_queue = fixed_queue_new(SIZE_MAX);if (btu_general_alarm_queue == NULL)goto error_exit;btu_oneshot_alarm_hash_map = hash_map_new(BTU_ONESHOT_ALARM_HASH_MAP_SIZE,hash_function_pointer, NULL, (data_free_fn)alarm_free, NULL);if (btu_oneshot_alarm_hash_map == NULL)goto error_exit;if (pthread_mutex_init(&btu_oneshot_alarm_lock, NULL))goto error_exit;btu_oneshot_alarm_queue = fixed_queue_new(SIZE_MAX);if (btu_oneshot_alarm_queue == NULL)goto error_exit;btu_l2cap_alarm_hash_map = hash_map_new(BTU_L2CAP_ALARM_HASH_MAP_SIZE,hash_function_pointer, NULL, (data_free_fn)alarm_free, NULL);if (btu_l2cap_alarm_hash_map == NULL)goto error_exit;if (pthread_mutex_init(&btu_l2cap_alarm_lock, NULL))goto error_exit;btu_l2cap_alarm_queue = fixed_queue_new(SIZE_MAX);if (btu_l2cap_alarm_queue == NULL)goto error_exit;bt_workqueue_thread = thread_new(BT_WORKQUEUE_NAME);if (bt_workqueue_thread == NULL)goto error_exit;// Continue startup on bt workqueue thread.thread_post(bt_workqueue_thread, btu_task_start_up, NULL);return;error_exit:;LOG_ERROR("%s Unable to allocate resources for bt_workqueue", __func__);BTU_ShutDown();
}

前面的都是错误判断,只看thread_post(bt_workqueue_thread, btu_task_start_up, NULL);就行了
Btu_task.c

void btu_task_start_up(UNUSED_ATTR void *context) {BT_TRACE(TRACE_LAYER_BTU, TRACE_TYPE_API,"btu_task pending for preload complete event");LOG_INFO("Bluetooth chip preload is complete");BT_TRACE(TRACE_LAYER_BTU, TRACE_TYPE_API,"btu_task received preload complete event");/* 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();/* Initialise platform trace levels at this point as BTE_InitStack() and bta_sys_init()* reset the control blocks and preset the trace level with XXX_INITIAL_TRACE_LEVEL*/
#if ( BT_USE_TRACES==TRUE )module_init(get_module(BTE_LOGMSG_MODULE));
#endif// Inform the bt jni thread initialization is ok.btif_transfer_context(btif_init_ok, 0, NULL, 0, NULL);fixed_queue_register_dequeue(btu_bta_msg_queue,thread_get_reactor(bt_workqueue_thread),btu_bta_msg_ready,NULL);fixed_queue_register_dequeue(btu_hci_msg_queue,thread_get_reactor(bt_workqueue_thread),btu_hci_msg_ready,NULL);fixed_queue_register_dequeue(btu_general_alarm_queue,thread_get_reactor(bt_workqueue_thread),btu_general_alarm_ready,NULL);fixed_queue_register_dequeue(btu_oneshot_alarm_queue,thread_get_reactor(bt_workqueue_thread),btu_oneshot_alarm_ready,NULL);fixed_queue_register_dequeue(btu_l2cap_alarm_queue,thread_get_reactor(bt_workqueue_thread),btu_l2cap_alarm_ready,NULL);
}

Btif_core.c

void btif_init_ok(UNUSED_ATTR uint16_t event, UNUSED_ATTR char *p_param) {BTIF_TRACE_DEBUG("btif_task: received trigger stack init event");
#if (BLE_INCLUDED == TRUE)btif_dm_load_ble_local_keys();
#endifBTA_EnableBluetooth(bte_dm_evt);
}
system/bt/bta/dm/Bta_dm_api.c
tBTA_STATUS BTA_EnableBluetooth(tBTA_DM_SEC_CBACK *p_cback)
{tBTA_DM_API_ENABLE    *p_msg;/* Bluetooth disabling is in progress */if (bta_dm_cb.disabling)return BTA_FAILURE;memset(&bta_dm_cb, 0, sizeof(bta_dm_cb));bta_sys_register (BTA_ID_DM, &bta_dm_reg );bta_sys_register (BTA_ID_DM_SEARCH, &bta_dm_search_reg );/* if UUID list is not provided as static data */bta_sys_eir_register(bta_dm_eir_update_uuid);if ((p_msg = (tBTA_DM_API_ENABLE *) GKI_getbuf(sizeof(tBTA_DM_API_ENABLE))) != NULL){p_msg->hdr.event = BTA_DM_API_ENABLE_EVT;p_msg->p_sec_cback = p_cback;bta_sys_sendmsg(p_msg);return BTA_SUCCESS;}return BTA_FAILURE;}
这里看看这个BTA_DM_API_ENABLE_EVT是什么,首先看看Bta_dm_int.h声明了一组枚举类型
enum
{/* device manager local device API events */BTA_DM_API_ENABLE_EVT = BTA_SYS_EVT_START(BTA_ID_DM),BTA_DM_API_DISABLE_EVT,
这个BTA_SYS_EVT_START又是什么?通过搜索在Bta_sys.h中找到了这个宏,这里先标志一下
#define BTA_SYS_EVT_START(id)       ((id) << 8)
system/bt/gki/common/Gki_buffer.c
void *GKI_getbuf (UINT16 size)
{BUFFER_HDR_T *header = osi_malloc(size + BUFFER_HDR_SIZE);header->status  = BUF_STATUS_UNLINKED;header->p_next  = NULL;header->Type    = 0;header->size = size;return header + 1;
}
system/bt/bta/sys/Bta_sys_main.c
void bta_sys_sendmsg(void *p_msg)
{// There is a race condition that occurs if the stack is shut down while// there is a procedure in progress that can schedule a task via this// message queue. This causes |btu_bta_msg_queue| to get cleaned up before// it gets used here; hence we check for NULL before using it.if (btu_bta_msg_queue)fixed_queue_enqueue(btu_bta_msg_queue, p_msg);
}

向消息队列发送msg,这个 btu_bta_msg_queue 是在Btu_init.c里面创建的

system/bt/stack/btu/Btu_init.c
void BTU_StartUp(void)
{memset (&btu_cb, 0, sizeof (tBTU_CB));btu_cb.trace_level = HCI_INITIAL_TRACE_LEVEL;btu_bta_msg_queue = fixed_queue_new(SIZE_MAX);if (btu_bta_msg_queue == NULL)goto error_exit;
......

相关处理函数在Btu_task.c里注册

system/bt/stack/btu/Btu_task.c
void btu_task_start_up(UNUSED_ATTR void *context) {
......fixed_queue_register_dequeue(btu_bta_msg_queue,thread_get_reactor(bt_workqueue_thread),btu_bta_msg_ready,NULL);
void btu_bta_msg_ready(fixed_queue_t *queue, UNUSED_ATTR void *context) {BT_HDR *p_msg = (BT_HDR *)fixed_queue_dequeue(queue);bta_sys_event(p_msg);
}
system/bt/bta/sys/Bta_sys_main.cvoid bta_sys_event(BT_HDR *p_msg)
{UINT8       id;BOOLEAN     freebuf = TRUE;APPL_TRACE_EVENT("BTA got event 0x%x", p_msg->event);/* get subsystem id from event */id = (UINT8) (p_msg->event >> 8);/* verify id and call subsystem event handler */if ((id < BTA_ID_MAX) && (bta_sys_cb.reg[id] != NULL)){freebuf = (*bta_sys_cb.reg[id]->evt_hdlr)(p_msg);}else{APPL_TRACE_WARNING("BTA got unregistered event id %d", id);}if (freebuf){GKI_freebuf(p_msg);}}

关键在于freebuf = (*bta_sys_cb.reg[id]->evt_hdlr)(p_msg);这个reg的赋值在

void bta_sys_register(UINT8 id, const tBTA_SYS_REG *p_reg)
{bta_sys_cb.reg[id] = (tBTA_SYS_REG *) p_reg;bta_sys_cb.is_reg[id] = TRUE;
}

那么,这个id是什么呢,就是上面我们标志的BTA_ID_DM

搜索bta_sys_register (BTA_ID_DM发现是在Bta_dm_api.c有调用

tBTA_STATUS BTA_EnableBluetooth(tBTA_DM_SEC_CBACK *p_cback)
{tBTA_DM_API_ENABLE    *p_msg;/* Bluetooth disabling is in progress */if (bta_dm_cb.disabling)return BTA_FAILURE;memset(&bta_dm_cb, 0, sizeof(bta_dm_cb));bta_sys_register (BTA_ID_DM, &bta_dm_reg );bta_sys_register (BTA_ID_DM_SEARCH, &bta_dm_search_reg );/* if UUID list is not provided as static data */bta_sys_eir_register(bta_dm_eir_update_uuid);if ((p_msg = (tBTA_DM_API_ENABLE *) GKI_getbuf(sizeof(tBTA_DM_API_ENABLE))) != NULL){p_msg->hdr.event = BTA_DM_API_ENABLE_EVT;p_msg->p_sec_cback = p_cback;bta_sys_sendmsg(p_msg);return BTA_SUCCESS;}return BTA_FAILURE;
static const tBTA_SYS_REG bta_dm_reg =
{bta_dm_sm_execute,bta_dm_sm_disable
};

然后在Bta_dm_main.c中

system/bt/bta/dm/Bta_dm_main.c
BOOLEAN bta_dm_sm_execute(BT_HDR *p_msg)
{UINT16  event = p_msg->event & 0x00ff;APPL_TRACE_EVENT("bta_dm_sm_execute event:0x%x", event);/* execute action functions */if(event < BTA_DM_NUM_ACTIONS){(*bta_dm_action[event])( (tBTA_DM_MSG*) p_msg);}return TRUE;
}

还记得吗,event=1<<8也就是256,化成二进制就是100000000(1和八个零),而0x00ff是011111111(0和八个一),两个&运算等于0,bta_dm_action的定义也在这个文件中

/* action function list */
const tBTA_DM_ACTION bta_dm_action[] =
{/* device manager local device API events */bta_dm_enable,            /* 0  BTA_DM_API_ENABLE_EVT */bta_dm_disable,           /* 1  BTA_DM_API_DISABLE_EVT */bta_dm_set_dev_name,      /* 2  BTA_DM_API_SET_NAME_EVT */bta_dm_set_visibility,    /* 3  BTA_DM_API_SET_VISIBILITY_EVT */bta_dm_acl_change,        /* 8  BTA_DM_ACL_CHANGE_EVT */bta_dm_add_device,        /* 9  BTA_DM_API_ADD_DEVICE_EVT */bta_dm_close_acl,        /* 10  BTA_DM_API_ADD_DEVICE_EVT *//* security API events */bta_dm_bond,              /* 11  BTA_DM_API_BOND_EVT */bta_dm_bond_cancel,       /* 12  BTA_DM_API_BOND_CANCEL_EVT */bta_dm_pin_reply,         /* 13 BTA_DM_API_PIN_REPLY_EVT */

bta_dm_enable的实现在Bta_dm_act中

void bta_dm_enable(tBTA_DM_MSG *p_data)
{tBTA_SYS_HW_MSG *sys_enable_event;tBTA_DM_ENABLE enable_event;/* if already in use, return an error */if( bta_dm_cb.is_bta_dm_active == TRUE  ){APPL_TRACE_WARNING("%s Device already started by another application", __func__);memset(&enable_event, 0, sizeof(tBTA_DM_ENABLE));enable_event.status = BTA_FAILURE;if (p_data->enable.p_sec_cback != NULL)p_data->enable.p_sec_cback(BTA_DM_ENABLE_EVT, (tBTA_DM_SEC *)&enable_event);return;}/* first, register our callback to SYS HW manager */bta_sys_hw_register( BTA_SYS_HW_BLUETOOTH, bta_dm_sys_hw_cback );/* make sure security callback is saved - if no callback, do not erase the previous one,it could be an error recovery mechanism */if( p_data->enable.p_sec_cback != NULL  )bta_dm_cb.p_sec_cback = p_data->enable.p_sec_cback;/* notify BTA DM is now active */bta_dm_cb.is_bta_dm_active = TRUE;/* send a message to BTA SYS */if ((sys_enable_event = (tBTA_SYS_HW_MSG *) GKI_getbuf(sizeof(tBTA_SYS_HW_MSG))) != NULL){sys_enable_event->hdr.event = BTA_SYS_API_ENABLE_EVT;sys_enable_event->hw_module = BTA_SYS_HW_BLUETOOTH;bta_sys_sendmsg(sys_enable_event);}
}

看注释应该没错了,前面通过 bta_dm_cb.is_bta_dm_active == TRUE判断是不是正在使用,后面有个 bta_dm_cb.is_bta_dm_active == TRUE,那么中间就应该是打开操作咯,

    /* first, register our callback to SYS HW manager */bta_sys_hw_register( BTA_SYS_HW_BLUETOOTH, bta_dm_sys_hw_cback );/* make sure security callback is saved - if no callback, do not erase the previous one,it could be an error recovery mechanism */if( p_data->enable.p_sec_cback != NULL  )bta_dm_cb.p_sec_cback = p_data->enable.p_sec_cback;

-_-!这不就两个注册回调函数吗!?我们再回头看看

看来  bta_sys_sendmsg(sys_enable_event)才是处理,这个和之前分析的一样,我们只要找到BTA_SYS_API_ENABLE_EVT的值,再找到对应的注册,就可以知道在哪处理的了

enum
{/* device manager local device API events */BTA_SYS_API_ENABLE_EVT = BTA_SYS_EVT_START(BTA_ID_SYS),BTA_SYS_EVT_ENABLED_EVT,BTA_SYS_EVT_STACK_ENABLED_EVT,BTA_SYS_API_DISABLE_EVT,BTA_SYS_EVT_DISABLED_EVT,BTA_SYS_ERROR_EVT,BTA_SYS_MAX_EVT
};

现在可以搜索注册bta_sys_register(BTA_ID_SYS 了,在Bta_sys_main中找到了

void bta_sys_init(void)
{memset(&bta_sys_cb, 0, sizeof(tBTA_SYS_CB));pthread_mutex_init(&bta_alarm_lock, NULL);bta_alarm_hash_map = hash_map_new(BTA_ALARM_HASH_MAP_SIZE,hash_function_pointer, NULL, (data_free_fn)alarm_free, NULL);btu_bta_alarm_queue = fixed_queue_new(SIZE_MAX);fixed_queue_register_dequeue(btu_bta_alarm_queue,thread_get_reactor(bt_workqueue_thread),btu_bta_alarm_ready,NULL);appl_trace_level = APPL_INITIAL_TRACE_LEVEL;/* register BTA SYS message handler */bta_sys_register( BTA_ID_SYS,  &bta_sys_hw_reg);/* register for BTM notifications */BTM_RegisterForDeviceStatusNotif ((tBTM_DEV_STATUS_CB*)&bta_sys_hw_btm_cback );#if( defined BTA_AR_INCLUDED ) && (BTA_AR_INCLUDED == TRUE)bta_ar_init();
#endif}static const tBTA_SYS_REG bta_sys_hw_reg =
{bta_sys_sm_execute,NULL
};BOOLEAN bta_sys_sm_execute(BT_HDR *p_msg)
{BOOLEAN freebuf = TRUE;tBTA_SYS_ST_TBL      state_table;UINT8               action;int                 i;APPL_TRACE_EVENT("bta_sys_sm_execute state:%d, event:0x%x",  bta_sys_cb.state, p_msg->event);/* look up the state table for the current state */state_table = bta_sys_st_tbl[bta_sys_cb.state];/* update state */bta_sys_cb.state = state_table[p_msg->event & 0x00ff][BTA_SYS_NEXT_STATE];/* execute action functions */for (i = 0; i < BTA_SYS_ACTIONS; i++){if ((action = state_table[p_msg->event & 0x00ff][i]) != BTA_SYS_IGNORE){(*bta_sys_action[action])( (tBTA_SYS_HW_MSG*) p_msg);}else{break;}}return freebuf;}

这里是状态模式了,状态模式的特点是不同状态响应命令有不同操作。首先BTA_ID_SYS=0,所以BTA_SYS_API_ENABLE_EVT=0<<8=0;

bta_sys_cb.state=bta_sys_hw_off,所以state_table = bta_sys_st_tbl[bta_sys_cb.state]

--》state_table = 
const UINT8 bta_sys_hw_off[][BTA_SYS_NUM_COLS] =
{
/* Event                    Action 1               Action 2             Next State */
/* API_ENABLE    */  {BTA_SYS_HW_API_ENABLE,    BTA_SYS_IGNORE,     BTA_SYS_HW_STARTING},
/* EVT_ENABLED   */  {BTA_SYS_IGNORE,           BTA_SYS_IGNORE,     BTA_SYS_HW_STARTING},
/* STACK_ENABLED */  {BTA_SYS_IGNORE,           BTA_SYS_IGNORE,     BTA_SYS_HW_ON},
/* API_DISABLE   */  {BTA_SYS_HW_EVT_DISABLED,  BTA_SYS_IGNORE,     BTA_SYS_HW_OFF},
/* EVT_DISABLED  */  {BTA_SYS_IGNORE,           BTA_SYS_IGNORE,     BTA_SYS_HW_OFF},
/* EVT_ERROR     */  {BTA_SYS_IGNORE,           BTA_SYS_IGNORE,     BTA_SYS_HW_OFF}
};

bta_sys_cb.state = state_table[p_msg->event & 0x00ff][BTA_SYS_NEXT_STATE]——》bta_sys_cb.state =BTA_SYS_HW_STARTING,下个状态是starting,进入循环,state_table【0】【0】=BTA_SYS_HW_API_ENABLE(下一次循环就break了),所以执行bta_sys_hw_api_enable

附:

/* state table */
const tBTA_SYS_ST_TBL bta_sys_st_tbl[] = {bta_sys_hw_off,bta_sys_hw_starting,bta_sys_hw_on,bta_sys_hw_stopping
};
/* state table for OFF state */
const UINT8 bta_sys_hw_off[][BTA_SYS_NUM_COLS] =
{
/* Event                    Action 1               Action 2             Next State */
/* API_ENABLE    */  {BTA_SYS_HW_API_ENABLE,    BTA_SYS_IGNORE,     BTA_SYS_HW_STARTING},
/* EVT_ENABLED   */  {BTA_SYS_IGNORE,           BTA_SYS_IGNORE,     BTA_SYS_HW_STARTING},
/* STACK_ENABLED */  {BTA_SYS_IGNORE,           BTA_SYS_IGNORE,     BTA_SYS_HW_ON},
/* API_DISABLE   */  {BTA_SYS_HW_EVT_DISABLED,  BTA_SYS_IGNORE,     BTA_SYS_HW_OFF},
/* EVT_DISABLED  */  {BTA_SYS_IGNORE,           BTA_SYS_IGNORE,     BTA_SYS_HW_OFF},
/* EVT_ERROR     */  {BTA_SYS_IGNORE,           BTA_SYS_IGNORE,     BTA_SYS_HW_OFF}
};const UINT8 bta_sys_hw_starting[][BTA_SYS_NUM_COLS] =
{
/* Event                    Action 1                   Action 2               Next State */
/* API_ENABLE    */  {BTA_SYS_IGNORE,               BTA_SYS_IGNORE,         BTA_SYS_HW_STARTING}, /* wait for completion event */
/* EVT_ENABLED   */  {BTA_SYS_HW_EVT_ENABLED,       BTA_SYS_IGNORE,         BTA_SYS_HW_STARTING},
/* STACK_ENABLED */  {BTA_SYS_HW_EVT_STACK_ENABLED, BTA_SYS_IGNORE,         BTA_SYS_HW_ON},
/* API_DISABLE   */  {BTA_SYS_IGNORE,               BTA_SYS_IGNORE,         BTA_SYS_HW_STOPPING}, /* successive disable/enable: change state wait for completion to disable */
/* EVT_DISABLED  */  {BTA_SYS_HW_EVT_DISABLED,      BTA_SYS_HW_API_ENABLE,  BTA_SYS_HW_STARTING}, /* successive enable/disable: notify, then restart HW */
/* EVT_ERROR */      {BTA_SYS_HW_ERROR,             BTA_SYS_IGNORE,         BTA_SYS_HW_ON}
};const UINT8 bta_sys_hw_on[][BTA_SYS_NUM_COLS] =
{
/* Event                    Action 1                   Action 2               Next State */
/* API_ENABLE    */  {BTA_SYS_HW_API_ENABLE,        BTA_SYS_IGNORE,         BTA_SYS_HW_ON},
/* EVT_ENABLED   */  {BTA_SYS_IGNORE,               BTA_SYS_IGNORE,         BTA_SYS_HW_ON},
/* STACK_ENABLED */  {BTA_SYS_IGNORE,               BTA_SYS_IGNORE,         BTA_SYS_HW_ON},
/* API_DISABLE   */  {BTA_SYS_HW_API_DISABLE,       BTA_SYS_IGNORE,         BTA_SYS_HW_ON}, /* don't change the state here, as some other modules might be active */
/* EVT_DISABLED */   {BTA_SYS_HW_ERROR,             BTA_SYS_IGNORE,         BTA_SYS_HW_ON},
/* EVT_ERROR */      {BTA_SYS_HW_ERROR,             BTA_SYS_IGNORE,         BTA_SYS_HW_ON}
};const UINT8 bta_sys_hw_stopping[][BTA_SYS_NUM_COLS] =
{
/* Event                    Action 1                   Action 2               Next State */
/* API_ENABLE    */  {BTA_SYS_IGNORE,               BTA_SYS_IGNORE,         BTA_SYS_HW_STARTING}, /* change state, and wait for completion event to enable */
/* EVT_ENABLED   */  {BTA_SYS_HW_EVT_ENABLED,       BTA_SYS_IGNORE,         BTA_SYS_HW_STOPPING}, /* successive enable/disable: finish the enable before disabling */
/* STACK_ENABLED */  {BTA_SYS_HW_EVT_STACK_ENABLED, BTA_SYS_HW_API_DISABLE, BTA_SYS_HW_STOPPING}, /* successive enable/disable: notify, then stop */
/* API_DISABLE   */  {BTA_SYS_IGNORE,               BTA_SYS_IGNORE,         BTA_SYS_HW_STOPPING}, /* wait for completion event */
/* EVT_DISABLED  */  {BTA_SYS_HW_EVT_DISABLED,      BTA_SYS_IGNORE,         BTA_SYS_HW_OFF},
/* EVT_ERROR     */  {BTA_SYS_HW_API_DISABLE,       BTA_SYS_IGNORE,         BTA_SYS_HW_STOPPING}
};

我们看下bta_sys_hw_api_enable方法

/*******************************************************************************
**
** Function         bta_sys_hw_enable
**
** Description     this function is called after API enable and HW has been turned on
**
**
** Returns          success or failure
**
*******************************************************************************/void bta_sys_hw_api_enable( tBTA_SYS_HW_MSG *p_sys_hw_msg )
{if ((!bta_sys_cb.sys_hw_module_active) && (bta_sys_cb.state != BTA_SYS_HW_ON)){/* register which HW module was turned on */bta_sys_cb.sys_hw_module_active |=  ((UINT32)1 << p_sys_hw_msg->hw_module );tBTA_SYS_HW_MSG *p_msg;if ((p_msg = (tBTA_SYS_HW_MSG *) GKI_getbuf(sizeof(tBTA_SYS_HW_MSG))) != NULL){p_msg->hdr.event = BTA_SYS_EVT_ENABLED_EVT;p_msg->hw_module = p_sys_hw_msg->hw_module;bta_sys_sendmsg(p_msg);}}else{/* register which HW module was turned on */bta_sys_cb.sys_hw_module_active |=  ((UINT32)1 << p_sys_hw_msg->hw_module );/* HW already in use, so directly notify the caller */if (bta_sys_cb.sys_hw_cback[p_sys_hw_msg->hw_module ]!= NULL )bta_sys_cb.sys_hw_cback[p_sys_hw_msg->hw_module ](  BTA_SYS_HW_ON_EVT   );}APPL_TRACE_EVENT ("bta_sys_hw_api_enable for %d, active modules 0x%04X",p_sys_hw_msg->hw_module, bta_sys_cb.sys_hw_module_active);}

-_-!这注释不是说已经打开了吗,莫非这状态机是为了回调,之前已经打开了?

网上查了很多,发现漏了一个很重要的地方,在bte_main.c的bte_main_enable()方法中,有句module_start_up(get_module(HCI_MODULE)),这个HCI_MODULE就是hci_layer.c,再看看module_start_up()方法,

bool module_start_up(const module_t *module) {assert(metadata != NULL);assert(module != NULL);// TODO(zachoverflow): remove module->init check once automagic order/call is in place.// This hack is here so modules which don't require init don't have to have useless calls// as we're converting the startup sequence.assert(get_module_state(module) == MODULE_STATE_INITIALIZED || module->init == NULL);if (!call_lifecycle_function(module->start_up)) {LOG_ERROR("%s failed to start up \"%s\"", __func__, module->name);return false;}set_module_state(module, MODULE_STATE_STARTED);return true;
}

会调用modle的start_up方法

static future_t *start_up(void) {......packet_fragmenter->init(&packet_fragmenter_callbacks);fixed_queue_register_dequeue(command_queue, thread_get_reactor(thread), event_command_ready, NULL);fixed_queue_register_dequeue(packet_queue, thread_get_reactor(thread), event_packet_ready, NULL);vendor->open(btif_local_bd_addr.address, &interface);hal->init(&hal_callbacks, thread);low_power_manager->init(thread);vendor->set_callback(VENDOR_CONFIGURE_FIRMWARE, firmware_config_callback);vendor->set_callback(VENDOR_CONFIGURE_SCO, sco_config_callback);vendor->set_callback(VENDOR_DO_EPILOG, epilog_finished_callback);if (!hci_inject->open(&interface)) {// TODO(sharvil): gracefully propagate failures from this layer.}int power_state = BT_VND_PWR_OFF;
#if (defined (BT_CLEAN_TURN_ON_DISABLED) && BT_CLEAN_TURN_ON_DISABLED == TRUE)LOG_WARN("%s not turning off the chip before turning on.", __func__);// So apparently this hack was needed in the past because a Wingray kernel driver// didn't handle power off commands in a powered off state correctly.// The comment in the old code said the workaround should be removed when the// problem was fixed. Sadly, I have no idea if said bug was fixed or if said// kernel is still in use, so we must leave this here for posterity. #sadpanda
#else// cycle power on the chip to ensure it has been resetvendor->send_command(VENDOR_CHIP_POWER_CONTROL, &power_state);
#endifpower_state = BT_VND_PWR_ON;vendor->send_command(VENDOR_CHIP_POWER_CONTROL, &power_state);startup_future = future_new();LOG_DEBUG("%s starting async portion", __func__);thread_post(thread, event_finish_startup, NULL);return startup_future;
error:;shut_down(); // returns NULL so no need to wait for itreturn future_new_immediate(FUTURE_FAIL);
}

vendor->open调用vendor.c的vendor_open(),调用厂商的open接口,后面vendor->send_command应该是上电操作。

android6.0 Bluetooth蓝牙源码流程笔记相关推荐

  1. Android 蓝牙源码学习笔记

    上文介绍了蓝牙基本原理和潜在的攻击面,但实现部分介绍不多,本文以 Android 中的蓝牙协议栈为例学习在实际系统中蓝牙的工程实现. 术语 在阅读源码的过程中发现许多函数名称带有意义不明的缩写,下面是 ...

  2. Android6.0的Looper源码分析(1)

    1      Looper简介 Android在Java标准线程模型的基础上,提供了消息驱动机制,用于多线程之间的通信.而其具体实现就是Looper. Android Looper的实现主要包括了3个 ...

  3. Android 8.1/9.0 MTK Camera源码分析之录像快门声音控制流程

    前面已经针对拍照快门声音控制流程进行了分析,接下来分析一下录像快门声音的控制流程. Android 8.1/9.0 MTK Camera源码分析之快门声音控制流程 这两篇文章其实都是相对于手机系统RO ...

  4. Android 8.1/9.0 MTK Camera源码分析之快门声音控制流程

    Android 8.1/9.0 MTK Camera源码分析之快门声音控制 在Android 8.1上mtk camera有控制快门声音的接口,但是并没有了控制录像快门声音的接口.之所以会有这个现象, ...

  5. iOS WebviewJavascriptBridge 源码研读笔记

    这两天接近元旦,事情稍微少些,有些时间,索性写点什么,就从最擅长的iOS混合开发写起了,由于iOS开发经验不到四年吧,期间还搞了一年半的前端,有些知识可能还是积累的不足,能力不足,水平有限,可能有谬误 ...

  6. 代码分析:NASM源码阅读笔记

    NASM源码阅读笔记 NASM(Netwide Assembler)的使用文档和代码间的注释相当齐全,这给阅读源码 提供了很大的方便.按作者的说法,这是一个模块化的,可重用的x86汇编器, 而且能够被 ...

  7. CI框架源码阅读笔记4 引导文件CodeIgniter.php

    到了这里,终于进入CI框架的核心了.既然是"引导"文件,那么就是对用户的请求.参数等做相应的导向,让用户请求和数据流按照正确的线路各就各位.例如,用户的请求url: http:// ...

  8. RocketMQ 源码学习笔记 Producer 是怎么将消息发送至 Broker 的?

    RocketMQ 源码学习笔记 Producer 是怎么将消息发送至 Broker 的? 文章目录 RocketMQ 源码学习笔记 Producer 是怎么将消息发送至 Broker 的? 前言 项目 ...

  9. 【Flink】Flink 源码阅读笔记(15)- Flink SQL 整体执行框架

    1.概述 转载:Flink 源码阅读笔记(15)- Flink SQL 整体执行框架 在数据处理领域,无论是实时数据处理还是离线数据处理,使用 SQL 简化开发将会是未来的整体发展趋势.尽管 SQL ...

最新文章

  1. JAVA I/O系统。
  2. 线段覆盖加强版(快速+贪心)
  3. 在云服务器上执行C程序和python程序(centos系统)
  4. linux6.5声卡驱动安装,详解CentOS 6.5如何安装Realtek无线网卡驱动
  5. python数据类型特点_Python 基础数据类型
  6. 于敦德:途牛五大战略纵深不惧同质化竞争
  7. java演出厅选票_高仿猫眼电影选座(选票)模块-b
  8. 前端基础-HTML标记语言
  9. 2022零售行业消费趋势新主张
  10. mysql kingshard_浅谈 Kingshard MySQL 中间件
  11. java 上文件传示例_Java解压缩文件示例
  12. win7 简体中文旗舰版 MSDN官方原版
  13. 计算机三级er图怎么画,visio2013怎么画ER图?
  14. 华为 eNSP 模拟器安装教程(内含下载地址)
  15. 如果软件测试是门艺术,软件测试工程师就是艺术家 -- 浅析ZStack是如何做智能软件测试
  16. Java小项目---电影购票系统
  17. Diablo2oo2s Universal Patcher(文件补丁工具) 2.18.3 绿色汉化版
  18. 如何判断插入的卡是SIM卡还是USIM卡
  19. 微信相册显示服务器偷懒,微信上这样「偷懒」,比使唤男朋友还省心!
  20. 使用MultiPowerOnOffTool工具 测试拔插网线对路由器的影响

热门文章

  1. buuctf MISC菜刀666
  2. 小米笔记本电脑故障——USB口拷贝文件中断/电池在低温时无输出
  3. 数据通信网络的基本概念
  4. 《安富莱嵌入式周报》第296期:硬件电路实现SPI转以太网,单片机3D游戏图形引擎,Linux基金会年度报告,安捷伦直流电源原理图,KEIL C51更新9.61
  5. win7设置wifi热点_Windows系统设置WIFI热点
  6. 若要运行此应用程序 您必须首先安装 .NET Framework的以下版本之一
  7. 在金融业务中跨行清算系统的实现过程
  8. JAVA外卖项目第一天 技术选型和包结构
  9. 2016文件储存服务器,测试Windows Server 2016存储池教程
  10. 时间触发嵌入式系统设计模式 读书笔记