在上一篇的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