在上一篇的BluetoothLeAdvertiser的分析中讲到,startAdvertising的内部具体实现都是IBluetoothGatt的引用来去实现的,这篇文章我们一起来往深的一层去分析。这篇博文我们会弄清楚上文中以下几点:
1.IBluetoothGatt的引用的到底是什么?
2. mClientIf是如何生成的以及作用?
先来看第一个问题——IBluetoothGatt的引用是什么?
这里可以先告诉大家上文中的IBluetoothGatt的引用的是com.android.bluetooth.gatt.GattService的实例。下面带大家看一下如何得出这个结论: 还记得上文中的以下代码吗? IBluetoothGatt gatt; try { gatt = mBluetoothManager.getBluetoothGatt(); } catch (RemoteException e) { Log.e(TAG, "Failed to get Bluetooth gatt - ", e); postStartFailure(callback, AdvertiseCallback.ADVERTISE_FAILED_INTERNAL_ERROR); return; } AdvertiseCallbackWrapper wrapper = new AdvertiseCallbackWrapper(callback, advertiseData,scanResponse, settings, gatt); wrapper.startRegisteration();
gatt的引用是通过mBluetoothManager.getBluetoothGatt()方法得到的,那么mBluetoothManager(这里可以先告诉大家mBluetoothManager是frameworks/base/services/core/java/com/android/server/BluetoothManagerService.java)又是什么,又是怎么来的?继续看代码:
/**
* Use BluetoothAdapter.getLeAdvertiser() instead.
*
* @param bluetoothManager BluetoothManager that conducts overall Bluetooth Management
* @hide
*/
public BluetoothLeAdvertiser(IBluetoothManager bluetoothManager) {
mBluetoothManager = bluetoothManager;
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
mHandler = new Handler(Looper.getMainLooper());
}
这个mBluetoothManager是通过参数传递过来的,但是这个构造函数是隐藏的,因为注解@hide。也就是这方法我们是不能在应用层直接调用的,事实上,我们在写代码时,获得BluetoothLeAdvertiser的实例也不是通过该构造函数,而是通过BluetoothAdapter.getBluetoothLeAdvertiser()。
/**
* Returns a {@link BluetoothLeAdvertiser} object for Bluetooth LE Advertising operations.
* Will return null if Bluetooth is turned off or if Bluetooth LE Advertising is not
* supported on this device.
* <p>
* Use {@link #isMultipleAdvertisementSupported()} to check whether LE Advertising is supported
* on this device before calling this method.
*/
public BluetoothLeAdvertiser getBluetoothLeAdvertiser() {
if (getState() != STATE_ON) {
return null;
}
if (!isMultipleAdvertisementSupported() && !isPeripheralModeSupported()) {
Log.e(TAG, "bluetooth le advertising not supported");
return null;
}
synchronized(mLock) {
if (sBluetoothLeAdvertiser == null) {
sBluetoothLeAdvertiser = new BluetoothLeAdvertiser(mManagerService);
}
}
return sBluetoothLeAdvertiser;
}
在BluetoothAdapter.getBluetoothLeAdvertiser方法中调用了BluetoothLeAdvertiser的构造函数并且传入了参数mManagerService,这个mManagerService又是怎么得到的呢?
/**BluetoothAdapter的代码
* Get a handle to the default local Bluetooth adapter.
* <p>Currently Android only supports one Bluetooth adapter, but the API
* could be extended to support more. This will always return the default
* adapter.
* @return the default local adapter, or null if Bluetooth is not supported
* on this hardware platform
*/
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;
}
/**
* Use {@link #getDefaultAdapter} to get the BluetoothAdapter instance.
*/
BluetoothAdapter(IBluetoothManager managerService) {
if (managerService == null) {
throw new IllegalArgumentException("bluetooth manager service is null");
}
try {
mService = managerService.registerAdapter(mManagerCallback);
} catch (RemoteException e) {Log.e(TAG, "", e);}
mManagerService = managerService;
mLeScanClients = new HashMap<LeScanCallback, ScanCallback>();
}
/*
*BluetoothManager的代码
* @hide
*/
public BluetoothManager(Context context) {
context = context.getApplicationContext();
if (context == null) {
throw new IllegalArgumentException(
"context not associated with any application (using a mock context?)");
}
// Legacy api - getDefaultAdapter does not take in the context
mAdapter = BluetoothAdapter.getDefaultAdapter();
}
/**
* Get the default BLUETOOTH Adapter for this device.
*
* @return the default BLUETOOTH Adapter
*/
public BluetoothAdapter getAdapter() {
return mAdapter;
}
我们在应用开发中往往会像下面的代码一样去获取一个BluetoothAdapter的实例.
mBluetoothManager=(BluetoothManager) mContext.getSystemService(Context.BLUETOOTH_SERVICE);//这句代码其实是在ContextImpl里调用了 new BluetoothManager(ctx)。
if(mBluetoothManager==null){
return ;
}
mBluetoothAdapter=mBluetoothManager.getAdapter();
if(mBluetoothAdapter==null){
return ;
}
下面看下mBluetoothManager引用的是什么
//frameworks/base/core/java/android/app/ContextImpl.java registerService(BLUETOOTH_SERVICE, new ServiceFetcher() {
public Object createService(ContextImpl ctx) {
return new BluetoothManager(ctx);
}});
也就是说,BluetoothAdapter的实例获得最终还是通过其getDefaultAdapter方法去调用构造函数创建的。BluetoothAdapter的构造函数的函数是通过
IBinder b = ServiceManager.getService(BLUETOOTH_MANAGER_SERVICE);
来获得的。
//frameworks/base/services/java/com/android/server/SystemServer.java // Skip Bluetooth if we have an emulator kernel
// TODO: Use a more reliable check to see if this product should
// support Bluetooth - see bug 988521
if (isEmulator) {
Slog.i(TAG, "No Bluetooh Service (emulator)");
} else if (mFactoryTestMode == FactoryTest.FACTORY_TEST_LOW_LEVEL) {
Slog.i(TAG, "No Bluetooth Service (factory test)");
} else if (!context.getPackageManager().hasSystemFeature
(PackageManager.FEATURE_BLUETOOTH)) {
Slog.i(TAG, "No Bluetooth Service (Bluetooth Hardware Not Present)");
} else if (disableBluetooth) {
Slog.i(TAG, "Bluetooth Service disabled by config");
} else {
Slog.i(TAG, "Bluetooth Manager Service");
bluetooth = new BluetoothManagerService(context);
ServiceManager.addService(BluetoothAdapter.BLUETOOTH_MANAGER_SERVICE, bluetooth);
}
看到上面的代码,我们终于找到在BluetoothLeAdvertiser中的
gatt = mBluetoothManager.getBluetoothGatt();
mBluetoothManager引用的实例了,那就是BluetoothManagerService的实例。既然找到了mBluetoothManager的实现,那么gatt的引用我们就可以在BluetoothManagerService的实现中去寻找了。
///frameworks/base/services/core/java/com/android/server/BluetoothManagerService.java
public IBluetoothGatt getBluetoothGatt() {
// sync protection
return mBluetoothGatt;//成员变量
}
- .................................
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);//BluetoothManagerService中只有这里对mBluetoothGatt进行了赋值操作,也就是之前我们一直念叨的gatt引用,结合上面的onServiceConnected的代码,可知引用的是GattService的对象
break;
} // else must be SERVICE_IBLUETOOTH
//Remove timeout
mHandler.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 ADDRESS
Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS);
mHandler.sendMessage(getMsg);
if (!mEnable) return;
}
mConnection.setGetNameAddressOnly(false);
//Register callback object
try {
mBluetooth.registerCallback(mBluetoothCallback);
} catch (RemoteException re) {
Log.e(TAG, "Unable to register BluetoothCallback",re);
}
//Inform BluetoothAdapter instances that service is up
sendBluetoothServiceUpCallback();
//Do enable request
try {
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;
}
.................................
说了这么多终于知道了
IBluetoothGatt的引用的是com.android.bluetooth.gatt.GattService的实例
也就是说,上篇文章中的发送和停止广播的行为的具体实现应该是在这个文件里。这里先不对其进行展开。
下面我们来看第二个问题:mClientIf是如何生成的以及作用?
既然上面的分析已经知道,最终的实现在GattService这个类里面,我直接来看一下,GattService的registerClient的方法
//http://androidxref.com/5.1.1_r6/xref/packages/apps/Bluetooth/src/com/android/bluetooth/gatt/GattService.java
void registerClient(UUID uuid, IBluetoothGattCallback callback) {
enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
if (DBG) Log.d(TAG, "registerClient() - UUID=" + uuid);
mClientMap.add(uuid, callback);
gattClientRegisterAppNative(uuid.getLeastSignificantBits(),uuid.getMostSignificantBits());//
}
//可以看到该方法是本地方法,所以我们要去找相应的JNI文件
private native void gattClientRegisterAppNative(long app_uuid_lsb, long app_uuid_msb);
也就是说AdvertiseCallbackWrapper里面的 mBluetoothGatt.registerClient(new ParcelUuid(uuid), this)最终调用的是gattClientRegisterAppNative方法。
找到对应的JNI文件:http://androidxref.com/5.1.1_r6/xref/packages/apps/Bluetooth/jni/com_android_bluetooth_gatt.cpp
static void gattClientRegisterAppNative(JNIEnv* env, jobject object,jlong app_uuid_lsb, jlong app_uuid_msb )
{
bt_uuid_t uuid;
if (!sGattIf) return;
set_uuid(uuid.uu, app_uuid_msb, app_uuid_lsb);
sGattIf->client->register_client(&uuid);
}
这时大家可以看到,具体的实现也不在这个方法里,没办法只能继续怼了。看一下sGattIf是什么?
static const btgatt_interface_t *sGattIf = NULL;
sGattIf的类型是btgatt_interface_t,来看一下相应的头,这个结构体是如何定义的,代码位于:http://androidxref.com/5.1.1_r6/xref/hardware/libhardware/include/hardware/bt_gatt.h#57
/** Represents the standard Bluetooth GATT interface. */
typedef struct {
/** Set to sizeof(btgatt_interface_t) */
size_t size;
/**
* Initializes the interface and provides callback routines
*/
bt_status_t (*init)( const btgatt_callbacks_t* callbacks );
/** Closes the interface */
void (*cleanup)( void );
/** Pointer to the GATT client interface methods.*/
const btgatt_client_interface_t* client;//上面的register_client肯定在这里面了
/** Pointer to the GATT server interface methods.*/
const btgatt_server_interface_t* server;
} btgatt_interface_t;
接着继续往下怼,看一下btgatt_client_interface_t,代码位于:http://androidxref.com/5.1.1_r6/xref/hardware/libhardware/include/hardware/bt_gatt_client.h
/** Represents the standard BT-GATT client interface. */
typedef struct {
/** Registers a GATT client application with the stack */
bt_status_t (*register_client)( bt_uuid_t *uuid );//** bt_uuid_t------Bluetooth 128-bit UUID,就是之前UUID.random生成的 */
/** Unregister a client application from the stack */
bt_status_t (*unregister_client)(int client_if );
/** Start or stop LE device scanning */
bt_status_t (*scan)( bool start );
/** Create a connection to a remote LE or dual-mode device */
bt_status_t (*connect)( int client_if, const bt_bdaddr_t *bd_addr,
bool is_direct, int transport );
/** Disconnect a remote device or cancel a pending connection */
bt_status_t (*disconnect)( int client_if, const bt_bdaddr_t *bd_addr,
int conn_id);
/** Start or stop advertisements to listen for incoming connections */
bt_status_t (*listen)(int client_if, bool start);
/** Clear the attribute cache for a given device */
bt_status_t (*refresh)( int client_if, const bt_bdaddr_t *bd_addr );
/**
* Enumerate all GATT services on a connected device.
* Optionally, the results can be filtered for a given UUID.
*/
bt_status_t (*search_service)(int conn_id, bt_uuid_t *filter_uuid );
/**
* Enumerate included services for a given service.
* Set start_incl_srvc_id to NULL to get the first included service.
*/
bt_status_t (*get_included_service)( int conn_id, btgatt_srvc_id_t *srvc_id,
btgatt_srvc_id_t *start_incl_srvc_id);
/**
* Enumerate characteristics for a given service.
* Set start_char_id to NULL to get the first characteristic.
*/
bt_status_t (*get_characteristic)( int conn_id,
btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *start_char_id);
/**
* Enumerate descriptors for a given characteristic.
* Set start_descr_id to NULL to get the first descriptor.
*/
bt_status_t (*get_descriptor)( int conn_id,
btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
btgatt_gatt_id_t *start_descr_id);
/** Read a characteristic on a remote device */
bt_status_t (*read_characteristic)( int conn_id,
btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
int auth_req );
/** Write a remote characteristic */
bt_status_t (*write_characteristic)(int conn_id,
btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
int write_type, int len, int auth_req,
char* p_value);
/** Read the descriptor for a given characteristic */
bt_status_t (*read_descriptor)(int conn_id,
btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
btgatt_gatt_id_t *descr_id, int auth_req);
/** Write a remote descriptor for a given characteristic */
bt_status_t (*write_descriptor)( int conn_id,
btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
btgatt_gatt_id_t *descr_id, int write_type, int len,
int auth_req, char* p_value);
/** Execute a prepared write operation */
bt_status_t (*execute_write)(int conn_id, int execute);
/**
* Register to receive notifications or indications for a given
* characteristic
*/
bt_status_t (*register_for_notification)( int client_if,
const bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
btgatt_gatt_id_t *char_id);
/** Deregister a previous request for notifications/indications */
bt_status_t (*deregister_for_notification)( int client_if,
const bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
btgatt_gatt_id_t *char_id);
/** Request RSSI for a given remote device */
bt_status_t (*read_remote_rssi)( int client_if, const bt_bdaddr_t *bd_addr);
/** Setup scan filter params */
bt_status_t (*scan_filter_param_setup)(int client_if, int action, int filt_index, int feat_seln,
int list_logic_type, int filt_logic_type, int rssi_high_thres,
int rssi_low_thres, int dely_mode, int found_timeout,
int lost_timeout, int found_timeout_cnt);
/** Configure a scan filter condition */
bt_status_t (*scan_filter_add_remove)(int client_if, int action, int filt_type,
int filt_index, int company_id,
int company_id_mask, const bt_uuid_t *p_uuid,
const bt_uuid_t *p_uuid_mask, const bt_bdaddr_t *bd_addr,
char addr_type, int data_len, char* p_data, int mask_len,
char* p_mask);
/** Clear all scan filter conditions for specific filter index*/
bt_status_t (*scan_filter_clear)(int client_if, int filt_index);
/** Enable / disable scan filter feature*/
bt_status_t (*scan_filter_enable)(int client_if, bool enable);
/** Determine the type of the remote device (LE, BR/EDR, Dual-mode) */
int (*get_device_type)( const bt_bdaddr_t *bd_addr );
/** Set the advertising data or scan response data */
bt_status_t (*set_adv_data)(int client_if, bool set_scan_rsp, bool include_name,
bool include_txpower, int min_interval, int max_interval, int appearance,
uint16_t manufacturer_len, char* manufacturer_data,
uint16_t service_data_len, char* service_data,
uint16_t service_uuid_len, char* service_uuid);
/** Configure the MTU for a given connection */
bt_status_t (*configure_mtu)(int conn_id, int mtu);
/** Request a connection parameter update */
bt_status_t (*conn_parameter_update)(const bt_bdaddr_t *bd_addr, int min_interval,
int max_interval, int latency, int timeout);
/** Sets the LE scan interval and window in units of N*0.625 msec */
bt_status_t (*set_scan_parameters)(int scan_interval, int scan_window);
/* Setup the parameters as per spec, user manual specified values and enable multi ADV */
bt_status_t (*multi_adv_enable)(int client_if, int min_interval,int max_interval,int adv_type,
int chnl_map, int tx_power, int timeout_s);
/* Update the parameters as per spec, user manual specified values and restart multi ADV */
bt_status_t (*multi_adv_update)(int client_if, int min_interval,int max_interval,int adv_type,
int chnl_map, int tx_power, int timeout_s);
/* Setup the data for the specified instance */
bt_status_t (*multi_adv_set_inst_data)(int client_if, bool set_scan_rsp, bool include_name,
bool incl_txpower, int appearance, int manufacturer_len,
char* manufacturer_data, int service_data_len,
char* service_data, int service_uuid_len, char* service_uuid);
/* Disable the multi adv instance */
bt_status_t (*multi_adv_disable)(int client_if);
/* Configure the batchscan storage */
bt_status_t (*batchscan_cfg_storage)(int client_if, int batch_scan_full_max,
int batch_scan_trunc_max, int batch_scan_notify_threshold);
/* Enable batchscan */
bt_status_t (*batchscan_enb_batch_scan)(int client_if, int scan_mode,
int scan_interval, int scan_window, int addr_type, int discard_rule);
/* Disable batchscan */
bt_status_t (*batchscan_dis_batch_scan)(int client_if);
/* Read out batchscan reports */
bt_status_t (*batchscan_read_reports)(int client_if, int scan_mode);
/** Test mode interface */
bt_status_t (*test_command)( int command, btgatt_test_params_t* params);
} btgatt_client_interface_t;
关于btgatt_client_interface_t的定义我没有做代码简略,以便大家对客户端接口的方法有个印象。既然我们找到了register_client方法的声明,我们就可以找到其实现。既然btgatt_client_interface_t是代表标准的BT-GATT客户端接口,那么我们就要找BT-GATT客户端接口的实现.几经跳转,终于找到其实现,代码位于:
http://androidxref.com/5.1.1_r6/xref/external/bluetooth/bluedroid/btif/src/btif_gatt_client.c
这里大家会好奇怎么就找到这个文件了呢?别急,听我慢慢到来,首先我们要看谁引用了bt_gatt_client.h,
经过搜索发现只有bt_gatt.h引用了bt_gatt_client.h,接着看谁引用了bt_gatt.h,搜索发现有很多个文件都引用了,但是最贴合我们的需求的就是btif_gatt_client.c。
下面看一下其部分代码:
/*******************************************************************************
*
* Filename: btif_gatt_client.c
*
* Description: GATT client implementation//可以看到这就是我们想要找的实现
*
*******************************************************************************/
/*******************************************************************************
** Client API Functions
********************************************************************************/
static bt_status_t btif_gattc_register_app(bt_uuid_t *uuid)//这个就对应registerClient方法
{
CHECK_BTGATT_INIT();
btif_gattc_cb_t btif_cb;//该结构体内部有个uuid,也有 uint8_t client_if字段,所以关键在这,浪里个浪
memcpy(&btif_cb.uuid, uuid, sizeof(bt_uuid_t));
return btif_transfer_context(btgattc_handle_event, BTIF_GATTC_REGISTER_APP,
(char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);//这里才是最终实现
}
static bt_status_t btif_gattc_unregister_app(int client_if )
{
CHECK_BTGATT_INIT();
btif_gattc_cb_t btif_cb;
btif_cb.client_if = (uint8_t) client_if;
return btif_transfer_context(btgattc_handle_event, BTIF_GATTC_UNREGISTER_APP,
(char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
}
static bt_status_t btif_gattc_scan( bool start )
{
CHECK_BTGATT_INIT();
btif_gattc_cb_t btif_cb;
return btif_transfer_context(btgattc_handle_event, start ? BTIF_GATTC_SCAN_START : BTIF_GATTC_SCAN_STOP,
(char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
}
最终实现还没有怼到,现在移步到http://androidxref.com/5.1.1_r6/xref/external/bluetooth/bluedroid/btif/src/btif_core.c#201看代码:
/*******************************************************************************
**
** Function btif_transfer_context
**
** Description This function switches context to btif task
**
** p_cback : callback used to process message in btif context
** event : event id of message//上面传入的是BTIF_GATTC_REGISTER_APP,即注册
** p_params : parameter area passed to callback (copied)----> 指上面代码中的btif_cb
** param_len : length of parameter area
** p_copy_cback : If set this function will be invoked for deep copy
**
** Returns void
**
*******************************************************************************/
bt_status_t btif_transfer_context (tBTIF_CBACK *p_cback, UINT16 event, char* p_params, int param_len, tBTIF_COPY_CBACK *p_copy_cback)
{
tBTIF_CONTEXT_SWITCH_CBACK *p_msg;
BTIF_TRACE_VERBOSE("btif_transfer_context event %d, len %d", event, param_len);
/* allocate and send message that will be executed in btif context */
if ((p_msg = (tBTIF_CONTEXT_SWITCH_CBACK *) GKI_getbuf(sizeof(tBTIF_CONTEXT_SWITCH_CBACK) + param_len)) != NULL)
{
p_msg->hdr.event = BT_EVT_CONTEXT_SWITCH_EVT; /* internal event */
p_msg->p_cb = p_cback;
p_msg->event = event; /* callback event */
/* check if caller has provided a copy callback to do the deep copy */
if (p_copy_cback)//上面调用中p_copy_cback传入是null
{
p_copy_cback(event, p_msg->p_param, p_params);
}
else if (p_params)
{
memcpy(p_msg->p_param, p_params, param_len); /* callback parameter data,这个回调参数,复制p_params到p_msg里的一个字段中 */
}
btif_sendmsg(p_msg);//现在可以肯定的是clientif的生成。
return BT_STATUS_SUCCESS;//这个就是注册成功了,啦啦
}
else
{
/* let caller deal with a failed allocation */
return BT_STATUS_NOMEM;
}
}
看到上面的代码,可以肯定的是client_if的生成肯定是在btif_sendmsg这个函数的一系列调用里面了,我们现在已经怼到了蓝牙协议栈的代码,即bluedroid 。到此为止吧,不怼了,如果大家真想继续怼,Please fuck bluedroid code!
下面我们一起来看看log:
com.android.bluetooth D/HeadsetStateMachine: Disconnected process message: 10, size: 0
com.android.bluetooth D/BtGatt.GattService: registerServer() - UUID=67bc6417-e673-4d91-8a25-28e8792554d0
com.android.bluetooth D/BtGatt.btif: btif_gatts_register_app
com.android.bluetooth D/BtGatt.btif: btgatts_handle_event: Event 2000
com.android.bluetooth E/bt-btif: register application first_unuse rcb_idx = 0
com.android.bluetooth D/BtGatt.btif: btapp_gatts_handle_cback: Event 0
com.android.bluetooth D/BtGatt.GattService: onServerRegistered() - UUID=67bc6417-e673-4d91-8a25-28e8792554d0, serverIf=4
com.android.bluetooth D/BtGatt.GattService: registerClient() - UUID=83edfbde-2553-4a0b-8682-01232ac6600c
com.android.bluetooth D/BtGatt.GattService: onClientRegistered() - UUID=83edfbde-2553-4a0b-8682-01232ac6600c, clientIf=5
com.android.bluetooth D/BtGatt.AdvertiseManager: message : 0
com.android.bluetooth D/BtGatt.AdvertiseManager: starting single advertising
com.android.bluetooth W/hcicmd: to do btsnd_hcic_ble_set_adv_enable 0x1
com.android.bluetooth D/hcicmd: Done btsnd_hcic_ble_set_adv_enable 0x1
com.android.bluetooth E/bt-btif: Listen For All now
com.android.bluetooth D/BtGatt.GattService: onAdvertiseCallback,- clientIf=5, status=0
com.android.bluetooth D/BtGatt.GattService: beginServiceDeclaration() - uuid=0000fee7-0000-1000-8000-00805f9b34fb
com.android.bluetooth D/BtGatt.GattService: addCharacteristic() - uuid=0000fec8-0000-1000-8000-00805f9b34fb
com.android.bluetooth D/BtGatt.GattService: addDescriptor() - uuid=00002902-0000-1000-8000-00805f9b34fb
com.android.bluetooth D/BtGatt.GattService: addCharacteristic() - uuid=0000fec7-0000-1000-8000-00805f9b34fb
com.android.bluetooth D/BtGatt.GattService: addDescriptor() - uuid=00002902-0000-1000-8000-00805f9b34fb
com.android.bluetooth D/BtGatt.GattService: addCharacteristic() - uuid=0000fec9-0000-1000-8000-00805f9b34fb
com.android.bluetooth D/BtGatt.GattService: addDescriptor() - uuid=00002902-0000-1000-8000-00805f9b34fb
com.android.bluetooth D/BtGatt.GattService: endServiceDeclaration()
com.android.bluetooth D/BtGatt.GattService: continueServiceDeclaration() - srvcHandle=0
com.android.bluetooth D/BtGatt.GattService: continueServiceDeclaration() - next entry type=1
com.android.bluetooth D/BtGatt.btif: btif_gatts_add_service
com.android.bluetooth D/BtGatt.btif: btgatts_handle_event: Event 2004
com.android.bluetooth E/bt-btif: create service rcb_idx = 0
com.android.bluetooth D/BtGatt.btif: btapp_gatts_handle_cback: Event 7
com.android.bluetooth D/BtGatt.GattService: onServiceAdded() UUID=0000fee7-0000-1000-8000-00805f9b34fb, status=0, handle=40
com.android.bluetooth D/BtGatt.GattService: continueServiceDeclaration() - srvcHandle=40
com.android.bluetooth D/BtGatt.GattService: continueServiceDeclaration() - next entry type=2
com.android.bluetooth D/BtGatt.btif: btif_gatts_add_characteristic
com.android.bluetooth D/BtGatt.btif: btgatts_handle_event: Event 2006
com.android.bluetooth D/BtGatt.btif: btapp_gatts_handle_cback: Event 9
com.android.bluetooth D/BtGatt.GattService: onCharacteristicAdded() UUID=0000fec8-0000-1000-8000-00805f9b34fb, status=0, srvcHandle=40, charHandle=42
com.android.bluetooth D/BtGatt.GattService: continueServiceDeclaration() - srvcHandle=40
com.android.bluetooth D/BtGatt.GattService: continueServiceDeclaration() - next entry type=3
com.android.bluetooth D/BtGatt.btif: btif_gatts_add_descriptor
com.android.bluetooth D/BtGatt.btif: btgatts_handle_event: Event 2007
com.android.bluetooth D/BtGatt.btif: btapp_gatts_handle_cback: Event 10
com.android.bluetooth D/BtGatt.GattService: onDescriptorAdded() UUID=00002902-0000-1000-8000-00805f9b34fb, status=0, srvcHandle=40, descrHandle=43
com.android.bluetooth D/BtGatt.GattService: continueServiceDeclaration() - srvcHandle=40
com.android.bluetooth D/BtGatt.GattService: continueServiceDeclaration() - next entry type=2
com.android.bluetooth D/BtGatt.btif: btif_gatts_add_characteristic
com.android.bluetooth D/BtGatt.btif: btgatts_handle_event: Event 2006
com.android.bluetooth D/BtGatt.btif: btapp_gatts_handle_cback: Event 9
com.android.bluetooth D/BtGatt.GattService: onCharacteristicAdded() UUID=0000fec7-0000-1000-8000-00805f9b34fb, status=0, srvcHandle=40, charHandle=45
com.android.bluetooth D/BtGatt.GattService: continueServiceDeclaration() - srvcHandle=40
com.android.bluetooth D/BtGatt.GattService: continueServiceDeclaration() - next entry type=3
com.android.bluetooth D/BtGatt.btif: btif_gatts_add_descriptor
com.android.bluetooth D/BtGatt.btif: btgatts_handle_event: Event 2007
com.android.bluetooth D/BtGatt.btif: btapp_gatts_handle_cback: Event 10
com.android.bluetooth D/BtGatt.GattService: onDescriptorAdded() UUID=00002902-0000-1000-8000-00805f9b34fb, status=0, srvcHandle=40, descrHandle=46
com.android.bluetooth D/BtGatt.GattService: continueServiceDeclaration() - srvcHandle=40
com.android.bluetooth D/BtGatt.GattService: continueServiceDeclaration() - next entry type=2
com.android.bluetooth D/BtGatt.btif: btif_gatts_add_characteristic
com.android.bluetooth D/BtGatt.btif: btgatts_handle_event: Event 2006
com.android.bluetooth D/BtGatt.btif: btapp_gatts_handle_cback: Event 9
com.android.bluetooth D/BtGatt.GattService: onCharacteristicAdded() UUID=0000fec9-0000-1000-8000-00805f9b34fb, status=0, srvcHandle=40, charHandle=48
com.android.bluetooth D/BtGatt.GattService: continueServiceDeclaration() - srvcHandle=40
com.android.bluetooth D/BtGatt.GattService: continueServiceDeclaration() - next entry type=3
com.android.bluetooth D/BtGatt.btif: btif_gatts_add_descriptor
com.android.bluetooth D/BtGatt.btif: btgatts_handle_event: Event 2007
com.android.bluetooth D/BtGatt.btif: btapp_gatts_handle_cback: Event 10
com.android.bluetooth D/BtGatt.GattService: onDescriptorAdded() UUID=00002902-0000-1000-8000-00805f9b34fb, status=0, srvcHandle=40, descrHandle=49
com.android.bluetooth D/BtGatt.GattService: continueServiceDeclaration() - srvcHandle=40
com.android.bluetooth D/BtGatt.btif: btif_gatts_start_service
com.android.bluetooth D/BtGatt.GattService: continueServiceDeclaration() - completed.
com.android.bluetooth D/BtGatt.btif: btgatts_handle_event: Event 2008
com.android.bluetooth D/BtGatt.btif: btapp_gatts_handle_cback: Event 12
com.android.bluetooth D/BtGatt.GattService: onServiceStarted() srvcHandle=40, status=0
com.android.bluetooth D/HeadsetStateMachine: Disconnected process message: 10, size: 0
com.android.bluetooth W/hcicmd: to do btsnd_hcic_ble_set_adv_enable 0x0
com.android.bluetooth D/hcicmd: Done btsnd_hcic_ble_set_adv_enable 0x0
com.android.bluetooth W/hcicmd: to do btsnd_hcic_ble_set_adv_enable 0x1
com.android.bluetooth D/hcicmd: Done btsnd_hcic_ble_set_adv_enable 0x1
com.general.testbluegattserverdemo D/BluetoothGattServer: registerCallback()
com.general.testbluegattserverdemo W/art: Suspending all threads took: 21.722ms
com.general.testbluegattserverdemo I/art: Background sticky concurrent mark sweep GC freed 1691(94KB) AllocSpace objects, 0(0B) LOS objects, 19% free, 486KB/605KB, paused 41.943ms total 149.288ms
com.general.testbluegattserverdemo D/BluetoothGattServer: registerCallback() - UUID=67bc6417-e673-4d91-8a25-28e8792554d0
com.general.testbluegattserverdemo I/art: Background partial concurrent mark sweep GC freed 2029(97KB) AllocSpace objects, 0(0B) LOS objects, 50% free, 502KB/1014KB, paused 908us total 115.721ms
com.general.testbluegattserverdemo D/BluetoothGattServer: onServerRegistered() - status=0 serverIf=4
com.general.testbluegattserverdemo D/BluetoothLeAdvertiser: onClientRegistered() - status=0 clientIf=5
com.general.testbluegattserverdemo D/OpenGLRenderer: Use EGL_SWAP_BEHAVIOR_PRESERVED: true
com.general.testbluegattserverdemo D/Atlas: Validating map...
com.general.testbluegattserverdemo E/ble: suceess
com.general.testbluegattserverdemo E/ble: not have wechat service
com.general.testbluegattserverdemo D/BluetoothGattServer: addService() - service: 0000fee7-0000-1000-8000-00805f9b34fb
com.general.testbluegattserverdemo D/BluetoothGattServer: onServiceAdded() - service=0000fee7-0000-1000-8000-00805f9b34fbstatus=0
com.general.testbluegattserverdemo E/Test Ble: status:0uuid:0000fee7-0000-1000-8000-00805f9b34fb
com.general.testbluegattserverdemo I/OpenGLRenderer: Initialized EGL, version 1.4
通过log我们可以看到clientIf是大于0的,上篇文章也说过mClientIf的值的含义,具体看上一篇文章的分析。
到此为止,该篇文章开头的第二个问题,我们简单做一下回答:
mClientIf是如何生成的以及作用?
clientIf的值是在bluedroid蓝牙协议栈的代码里生成的,要知道具体怎么生成的,可以根据该篇文章继续怼。
mClientIf=0——>未注册;mClinetIf=-1——>广播停止或注册超时;mClientIf>0——>已注册并且已经广播成功
至于作用就是根据其值做不同的逻辑业务处理啦。
开篇的两个问题算是回答完了,也即我们怼完了 mBluetoothGatt.registerClient(new ParcelUuid(uuid), this)这个方法,仅仅是注册过程怼完了,还有广播流程没有怼,放到下篇文章里继续怼。
由于源码的复杂性与庞大,这里文字表达的不是非常清晰,请谅解,如果你从该篇文章领悟到怼源码的姿势,那才是最大的收获。
转载请注明出处:http://blog.csdn.net/android_jiangjun/article/details/77982980