Android 蓝牙启动流程(以及设置蓝牙为作为sink模式 & 接收端模式)

本文以Android 7.1为基础

最近在做蓝牙开发,研究了一下蓝牙的启动流程,总结一下

Google在Android源码中推出了它和博通公司一起开发的BlueDroid以替代BlueZ。BlueZ的创始者,高通公司也将在基于其芯片的Android参考设计中去除BlueZ,支持BlueDroid。相比BlueZ,BlueDroid最值得称道的地方就是其框架结构变得更为简洁和清晰。对我们工程师来说这也是个不错的福利,清晰、简洁的架构使我们在debug过程中思路更清晰;

蓝牙的总体流程图

从流程图我们可以看出来 蓝牙应用通过binder和系统蓝牙Service进行通讯 ,然后通过Jin与蓝牙HAL层进行通讯.

按层级划分

Bluetooth Service(Java层)代码路径

frameworks/base/core/java/Android/Bluetooth:

Bluetooth 应用层代码路径

packages/apps/Bluetooth

Bluetooth协议层代码

system/bt/

涉及的总共路径:

1frameworks/base/core/java/android/bluetooth/BluetoothAdapter.java 2frameworks/base/core/java/android/bluetooth/BluetoothManagerService.java 3packages/apps/Bluetooth/src/com/android/bluetooth/btservice/AdapterService.java 4packages/apps/Bluetooth/src/com/android/bluetooth/btservice/AdapterState.java 5packages/apps/Bluetooth/jni/com_android_bluetooth_btservice_AdapterService.cpp 6system/bt/btif/src/btif_dm.c 7system/bt/btif/include/btif_common.h 8hardware/libhardware/include/hardware/bluetooth.h 

一.将蓝牙作为sink模式 配置

sink模式一般是车机端需要设置的模式,用于链接手机之后可以播放蓝牙音乐,获取联系人,和电话控制等等

1packages/apps/Bluetooth/src/com/android/bluetooth/btservice/Config.java 2有如下两个参数控制是否是 sink端 3 4boolean isA2dpSinkEnabled = SystemProperties.getBoolean("persist.service.bt.a2dp.sink", false); 5 boolean isHfpClientEnabled = SystemProperties.getBoolean("persist.service.bt.hfp.client",false);

我们需要在编译源码的时候去配置成sink模式

1device/qcom/msmxxx_64/system.prop 2添加如下配置 3 4persist.service.bt.a2dp.sink=true 5persist.service.bt.hfp.client=true

再具体的配置信息在如下配置中进行设置具体支持那种profile

1packages/apps/Bluetooth/res/values/config.xml 2 3<resources> 4 <bool name="profile_supported_a2dp">true</bool> 5 <bool name="profile_supported_a2dp_sink">false</bool> 6 <bool name="profile_supported_hdp">true</bool> 7 <bool name="profile_supported_hs_hfp">true</bool> 8 <bool name="profile_supported_hfpclient">false</bool> 9 <bool name="profile_supported_hid">true</bool> 10 <bool name="profile_supported_opp">true</bool> 11 <bool name="profile_supported_pan">true</bool> 12 <bool name="profile_supported_pbap">true</bool> 13 <bool name="profile_supported_gatt">true</bool> 14 <bool name="pbap_include_photos_in_vcard">true</bool> 15 <bool name="pbap_use_profile_for_owner_vcard">true</bool> 16 <bool name="profile_supported_map">true</bool> 17 <bool name="profile_supported_avrcp_controller">false</bool> 18 <bool name="profile_supported_sap">false</bool> 19 <bool name="profile_supported_pbapclient">false</bool> 20 <bool name="strict_location_check">true</bool> 21</resources>

当然修改上面的配置我们可以在如下路径配置

1vendor/qcom/opensource/bluetooth/res/values/config.xml 2 3 4<resources> 5 <bool name="profile_supported_ftp">true</bool> 6 <bool name="profile_supported_map">false</bool> 7 <bool name="profile_supported_sap">true</bool> 8 <bool name="profile_supported_dun">true</bool> 9</resources>

如果 packages/apps/Bluetooth/res/values/config.xml 和 vendor/qcom/opensource/bluetooth/res/values/config.xml 都配置了如下配置 或者是配置的两个Boolean 值是反向的,系统会依据 vendor/qcom/opensource/bluetooth/res/values/config.xml 配置为最终结果,配置完成之后编译系统,烧录系统就可以作为sink端使用,也就是接收端.

二.启动流程分析

首先我们调用蓝牙的时候使用的是Bluetooth的 BluetoothAdapter.java 类 中的enable方法

路径如下

frameworks/base/core/java/android/bluetooth/BluetoothAdapter.java

1 public boolean enable() { 2 android.util.SeempLog.record(56); 3 if (isEnabled()) { 4 if (DBG) Log.d(TAG, "enable(): BT already enabled!"); 5 return true; 6 } 7 try { 8 // 此处调用的是 IBluetoothManager.java的 enable 9 return mManagerService.enable(ActivityThread.currentPackageName()); 10 } catch (RemoteException e) {Log.e(TAG, "", e);} 11 return false; 12 }

我们查看到 IBluetoothManager.java的实现类是BluetoothManagerService.java , BluetoothManagerService.java

1class BluetoothManagerService extends IBluetoothManager.Stub { 2 .....省略代码..... 3 public boolean enable(String packageName) throws RemoteException { 4 final int callingUid = Binder.getCallingUid(); 5 final boolean callerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID; 6 .....省略代码..... 7 // 权限检查 8 .....省略代码..... 9 10 synchronized(mReceiver) { 11 mQuietEnableExternal = false; 12 mEnableExternal = true; 13 // waive WRITE_SECURE_SETTINGS permission check 14 sendEnableMsg(false, packageName); 15 } 16 if (DBG) Slog.d(TAG, "enable returning"); 17 return true; 18 } 19 .....省略代码..... 20}

我们继续查看可以看到调用的是 sendEnableMsg(boolean quietMode, String packageName) 方法.

1 private void sendEnableMsg(boolean quietMode, String packageName) { 2 mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_ENABLE, 3 quietMode ? 1 : 0, 0)); 4 addActiveLog(packageName, true); 5 }

在sendEnableMsg 方法中 发送了一个message消息 MESSAGE_ENABLE

1 case MESSAGE_ENABLE: 2 3 try { 4 if (mBluetooth != null) { 5 int state = mBluetooth.getState(); 6 if (state == BluetoothAdapter.STATE_BLE_ON) { 7 //如果蓝牙已经打开调用 BluetoothAdapterService.java 开启profile 8 mBluetooth.onLeServiceUp(); 9 //保存蓝牙的开关状态 10 persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH); 11 break; 12 } 13 } 14 } 15 mQuietEnable = (msg.arg1 == 1); 16 //如果没有蓝牙没有打开去打开蓝牙 17 if (mBluetooth == null) { 18 handleEnable(mQuietEnable); 19 } else { 20 21 if(state == BluetoothAdapter.STATE_TURNING_OFF || state == BluetoothAdapter.STATE_BLE_TURNING_OFF) 22 waitForMonitoredOnOff(false, true); 23 //重启蓝牙 24 Message restartMsg = mHandler.obtainMessage( 25 MESSAGE_RESTART_BLUETOOTH_SERVICE); 26 mHandler.sendMessageDelayed(restartMsg, 27 2 * SERVICE_RESTART_TIME_MS); 28 } 29 break;

在 MESSAGE_ENABLE 接收的消息中会先判断盘牙是否打开,如果已经打开 就调用mBluetooth.onLeServiceUp();去打开 Profile文件如果没有打开就调用handleEnable(mQuietEnable);去打开蓝牙. 咱们这里先不看 mBluetooth.onLeServiceUp(); 方法先查看handleEnable(mQuietEnable)

1private void handleEnable(boolean quietMode) { 2 3 if ((mBluetooth == null) && (!mBinding)) { 4 //蓝牙打开超时记录 5 Message timeoutMsg=mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND); 6 mHandler.sendMessageDelayed(timeoutMsg,TIMEOUT_BIND_MS); 7 Intent i = new Intent(IBluetooth.class.getName()); 8 //此处我们查看到 mConnection 方法是链接状态的回调 9 if (!doBind(i, mConnection,Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT, 10 UserHandle.CURRENT)) { 11 mHandler.removeMessages(MESSAGE_TIMEOUT_BIND); 12 } else { 13 mBinding = true; 14 } 15 } 16 }

其中mConnection 是链接的回调 BluetoothServiceConnection 就是 mConnection 类

在BluetoothServiceConnection 类中会发送   MESSAGE_BLUETOOTH_SERVICE_CONNECTED 消息并传递了一个 AdapterService对象.

1 private class BluetoothServiceConnection implements ServiceConnection { 2 public void onServiceConnected(ComponentName componentName, IBinder service) { 3 String name = componentName.getClassName(); 4 if (DBG) Slog.d(TAG, "BluetoothServiceConnection: " + name); 5 Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_CONNECTED); 6 if (name.equals("com.android.bluetooth.btservice.AdapterService")) { 7 msg.arg1 = SERVICE_IBLUETOOTH; 8 } 9 msg.obj = service; 10 mHandler.sendMessage(msg); 11 } 12 13 public void onServiceDisconnected(ComponentName componentName) { 14 // Called if we unexpectedly disconnect. 15 String name = componentName.getClassName(); 16 if (DBG) Slog.d(TAG, "BluetoothServiceConnection, disconnected: " + name); 17 Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED); 18 if (name.equals("com.android.bluetooth.btservice.AdapterService")) { 19 msg.arg1 = SERVICE_IBLUETOOTH; 20 } 21 mHandler.sendMessage(msg); 22 } 23 }

我们继续追踪  MESSAGE_BLUETOOTH_SERVICE_CONNECTED消息

1 case MESSAGE_BLUETOOTH_SERVICE_CONNECTED: 2 { 3 IBinder service = (IBinder) msg.obj; 4 mBinding = false; 5 mBluetoothBinder = service; 6 mBluetooth = IBluetooth.Stub.asInterface(service); 7 //注册 CallBack 重要,后面的回调要使用 8 try { 9 mBluetooth.registerCallback(mBluetoothCallback); 10 } catch (RemoteException re) { 11 Slog.e(TAG, "Unable to register BluetoothCallback",re); 12 } 13 //Do enable request 14 try { 15 //打开蓝牙请求 16 if (mQuietEnable == false) { 17 if (!mBluetooth.enable()) { 18 Slog.e(TAG,"IBluetooth.enable() returned false"); 19 } 20 } 21 } 22 break; 23 }

MESSAGE_BLUETOOTH_SERVICE_CONNECTED消息里面可以查看到 mBluetooth = IBluetooth.Stub.asInterface(service);获取的是 IBluetooth 对象 , 而AdapterService.java 内部类 AdapterServiceBinder  实现了 IBluetooth

packages/apps/Bluetooth/src/com/android/bluetooth/btservice/AdapterService.java

1 private static class AdapterServiceBinder extends IBluetooth.Stub { 2 private AdapterService mService; 3 4 public AdapterService getService() { 5 if (mService != null && mService.isAvailable()) { 6 return mService; 7 } 8 return null; 9 } 10 11 public boolean enable() { 12 ........ 13 AdapterService service = getService(); 14 if (service == null) return false; 15 return service.enable(); 16 } 17 }

由上面可以看出 return service.enable();调用的是 AdapterService.java 中的方法 enable() 方法

1 public synchronized boolean enable(boolean quietMode) { 2 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); 3 4 debugLog("enable() - Enable called with quiet mode status = " + mQuietmode); 5 mQuietmode = quietMode; 6 Message m = mAdapterStateMachine.obtainMessage(AdapterState.BLE_TURN_ON); 7 mAdapterStateMachine.sendMessage(m); 8 mBluetoothStartTime = System.currentTimeMillis(); 9 return true; 10 }

发送的是 BLE_TURN_ON

packages/apps/Bluetooth/src/com/android/bluetooth/btservice/AdapterState.java 接受了这个消息

1 case BLE_TURN_ON: 2 notifyAdapterStateChange(BluetoothAdapter.STATE_BLE_TURNING_ON); 3 //将蓝牙的状态转换成 mPendingCommandState 4 mPendingCommandState.setBleTurningOn(true); 5 transitionTo(mPendingCommandState); 6 sendMessageDelayed(BLE_START_TIMEOUT, BLE_START_TIMEOUT_DELAY); 7 adapterService.BleOnProcessStart(); 8 break;

将了蓝牙的状态转换成 mPendingCommandState 调用 BleOnProcessStart 方法,也可以在supportedProfileServices  方法中去掉自己不想开启的ProfileService.

1 void BleOnProcessStart() { 2 3 //获取支持的profile 文件 4 Class[] supportedProfileServices = Config.getSupportedProfiles(); 5 //Initialize data objects 6 for (int i=0; i < supportedProfileServices.length;i++) { 7 mProfileServicesState.put(supportedProfileServices[i].getName(),BluetoothAdapter.STATE_OFF); 8 } 9 mRemoteDevices.cleanup(); 10 mAdapterProperties.init(mRemoteDevices); 11 mJniCallbacks.init(mBondStateMachine,mRemoteDevices); 12 //Start Gatt service 13 //调用 ProfileService 14 setGattProfileServiceState(supportedProfileServices,BluetoothAdapter.STATE_ON); 15 }

获取支持的ProfileService列表.

1 private static final Class[] PROFILE_SERVICES = { 2 HeadsetService.class, 3 A2dpService.class, 4 A2dpSinkService.class, 5 HidService.class, 6 HealthService.class, 7 PanService.class, 8 GattService.class, 9 BluetoothMapService.class, 10 HeadsetClientService.class, 11 AvrcpControllerService.class, 12 SapService.class, 13 PbapClientService.class 14 };

//发送  ACTION_SERVICE_STATE_CHANGED参数 每一个profile 都有 遍历开启 profile

1 private void setGattProfileServiceState(Class[] services, int state) { 2 3 for (int i=0; i <services.length;i++) { 4 mProfileServicesState.put(serviceName,pendingState); 5 Intent intent = new Intent(this,services[i]); 6 intent.putExtra(EXTRA_ACTION,ACTION_SERVICE_STATE_CHANGED); 7 intent.putExtra(BluetoothAdapter.EXTRA_STATE,state); 8 startService(intent); 9 return; 10 } 11 } 12 } 13 14 public int onStartCommand(Intent intent, int flags, int startId) { 15 if (intent == null) { 16 Log.d(mName, "Restarting profile service..."); 17 return PROFILE_SERVICE_MODE; 18 } else { 19 String action = intent.getStringExtra(AdapterService.EXTRA_ACTION); 20 if (AdapterService.ACTION_SERVICE_STATE_CHANGED.equals(action)) { 21 } else if (state == BluetoothAdapter.STATE_ON) { 22 ........省略代码...... 23 // 开启服务 24 doStart(intent); 25 } 26 } 27 return PROFILE_SERVICE_MODE; 28 }

 调用doStartService之后 我们可以看到调用了 notifyProfileServiceStateChanged 方法。

1 private void doStart(Intent intent) { 2 3 if (!mStartError) { 4 // 开始调用 notifyProfileServiceStateChanged 5 notifyProfileServiceStateChanged(BluetoothAdapter.STATE_ON); 6 } 7 }

继续查看notifyProfileServiceStateChanged 方法 ,里面又回到了AdapterServer 中的 onProfileServiceStateChanged方法

1 protected void notifyProfileServiceStateChanged(int state) { 2 //Notify adapter service 3 AdapterService adapterService = AdapterService.getAdapterService(); 4 if (adapterService != null) { 5 adapterService.onProfileServiceStateChanged(getClass().getName(), state); 6 } 7 }

发送MESSAGE_PROFILE_SERVICE_STATE_CHANGED 消息 给消息处理

1 public void onProfileServiceStateChanged(String serviceName, int state) { 2 Message m = mHandler.obtainMessage(MESSAGE_PROFILE_SERVICE_STATE_CHANGED); 3 m.obj=serviceName; 4 m.arg1 = state; 5 mHandler.sendMessage(m); 6 }

在消息接收的地方查看到蓝牙的 processProfileServiceStateChanged 方法被调用,在processProfileServiceStateChanged 方法中发送了 BLE_STARTED 消息,而这个消息接受的地方是开起底层ProfileService的地方。

1 case MESSAGE_PROFILE_SERVICE_STATE_CHANGED: { 2 debugLog("handleMessage() - MESSAGE_PROFILE_SERVICE_STATE_CHANGED"); 3 processProfileServiceStateChanged((String) msg.obj, msg.arg1); 4 } 5 break; 6 7 private void processProfileServiceStateChanged(String serviceName, int state) { 8 9 if (isBleTurningOn) { 10 if (serviceName.equals("com.android.bluetooth.gatt.GattService")) { 11 debugLog("GattService is started"); 12 mAdapterStateMachine.sendMessage(mAdapterStateMachine.obtainMessage(AdapterState.BLE_STARTED)); 13 return; 14 } 15 16 } 17 }

/packages/apps/Bluetooth/src/com/android/bluetooth/btservice/AdapterState.java BLE_STARTED消息处理任务,通过 adapterService.enableNative(isGuest) 开启底层的profileService。

1 case BLE_STARTED: 2 //开启底层服务 3 if (!adapterService.enableNative(isGuest)) { 4 errorLog("Error while turning Bluetooth on"); 5 notifyAdapterStateChange(BluetoothAdapter.STATE_OFF); 6 transitionTo(mOffState); 7 } 8 break;

调用的是 AdapterService.java 中的native方法 ,根据包名和JNI 方法的名称我们可以推算出来调用的CPP的名称是 com_android_bluetooth_btservice_AdapterService.cpp

 /*package*/ native boolean enableNative(boolean startRestricted);

在如下路径找到了 packages/apps/Bluetooth/jni/com_android_bluetooth_btservice_AdapterService.cpp 在enableNative中查看到 int ret = sBluetoothInterface->enable(isGuest == JNI_TRUE ? 1 : 0); 调用的是 sBluetoothInterface 中的enable方法

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

具体的实现在 bluetooth.c中。

/system/bt/btif/src/bluetooth.c

1static int enable(bool start_restricted) { 2 LOG_INFO(LOG_TAG, "%s: start restricted = %d", __func__, start_restricted); 3 4 restricted_mode = start_restricted; 5 6 if (!interface_ready()) 7 return BT_STATUS_NOT_READY; 8 9 stack_manager_get_interface()->start_up_stack_async(); 10 return BT_STATUS_SUCCESS; 11}

底层回调传递到上层的时候主要使用的是 btif_dm.c 中对消息的处理 BTA_DM_INQ_RES_EVT 消息

system/bt/btif/src/btif_dm.c

1static void btif_dm_search_devices_evt (UINT16 event, char *p_param) 2{ 3 ...省略代码..... 4 case BTA_DM_INQ_RES_EVT: 5 ...省略代码..... 6 /* Callback to notify upper layer of device */ 7 HAL_CBACK(bt_hal_cbacks, device_found_cb, 8 num_properties, properties); 9 10 break;

/system/bt/btif/include/btif_common.h

define HAL_CBACK(P_CB, P_CBACK, ...) 方法 , HAL_CBACK就是一宏定义,就是调用结构体中对应的方法

1extern bt_callbacks_t *bt_hal_cbacks; 2 3#define HAL_CBACK(P_CB, P_CBACK, ...)\ 4 if (P_CB && P_CB->P_CBACK) { \ 5 BTIF_TRACE_API("HAL %s->%s", #P_CB, #P_CBACK); \ 6 P_CB->P_CBACK(__VA_ARGS__); \ 7 } \ 8 else { \ 9 ASSERTC(0, "Callback is NULL", 0); \ 10 }

bt_hal_cbacks 其实就是 蓝牙AdapterService中调用了initNative方法传入到底层的。看下jni中的initNative方法:

1 @Override 2 public void onCreate() { 3 super.onCreate(); 4 .......... 5 //调用底层方法 6 initNative(); 7 8 ........ 9 10 } 11 12private native boolean initNative();

调用com_android_bluetooth_btservice_AdapterService.cpp init方法 将Callback传递到底层

1static bool initNative(JNIEnv* env, jobject obj) { 2 ....... 3 //调用com_android_bluetooth_btservice_AdapterService.cpp init方法 将Callback传递到底层 4 // 再调用 bluetooth.c 的 init方法 5 6 int ret = sBluetoothInterface->init(&sBluetoothCallbacks); 7 8 ....... 9}

com_android_bluetooth_btservice_AdapterService.cpp  再调用 bluetooth.c 的 init方法

1static int init(bt_callbacks_t *callbacks) { 2 CallBack传递到底层 3 bt_hal_cbacks = callbacks; 4 stack_manager_get_interface()->init_stack(); 5 6}

其实这里有两个地方有  bt_callbacks_t  我们可以对比看一下

1./hardware/libhardware/include/hardware/bluetooth.h

2. /packages/apps/Bluetooth/jni/com_android_bluetooth_btservice_AdapterService.cpp

1bluetooth.h 中的 bt_callbacks_t 2 3typedef struct { 4 /** set to sizeof(bt_callbacks_t) */ 5 size_t size; 6 adapter_state_changed_callback adapter_state_changed_cb; 7 adapter_properties_callback adapter_properties_cb; 8 remote_device_properties_callback remote_device_properties_cb; 9 device_found_callback device_found_cb; 10 discovery_state_changed_callback discovery_state_changed_cb; 11 pin_request_callback pin_request_cb; 12 ssp_request_callback ssp_request_cb; 13 bond_state_changed_callback bond_state_changed_cb; 14 acl_state_changed_callback acl_state_changed_cb; 15 callback_thread_event thread_evt_cb; 16 dut_mode_recv_callback dut_mode_recv_cb; 17 le_test_mode_callback le_test_mode_cb; 18 energy_info_callback energy_info_cb; 19} bt_callbacks_t; 20 21 22 23// com_android_bluetooth_btservice_AdapterService.cpp 中的 bt_callbacks_t 24static bt_callbacks_t sBluetoothCallbacks = { 25 sizeof(sBluetoothCallbacks), 26 adapter_state_change_callback, 27 adapter_properties_callback, 28 remote_device_properties_callback, 29 device_found_callback, 30 discovery_state_changed_callback, 31 pin_request_callback, 32 ssp_request_callback, 33 bond_state_changed_callback, 34 acl_state_changed_callback, 35 callback_thread_event, 36 dut_mode_recv_callback, 37 le_test_mode_recv_callback, 38 energy_info_recv_callback 39}; 40 41static bt_callbacks_t sBluetoothCallbacks = { 42 sizeof(sBluetoothCallbacks), 43 adapter_state_change_callback, 44 adapter_properties_callback, 45 remote_device_properties_callback, 46 device_found_callback, 47 discovery_state_changed_callback, 48 pin_request_callback, 49 ssp_request_callback, 50 bond_state_changed_callback, 51 acl_state_changed_callback, 52 callback_thread_event, 53 dut_mode_recv_callback, 54 le_test_mode_recv_callback, 55 energy_info_recv_callback 56};

最后蓝牙驱动打开之后会通过

/system/bt/btif/src/btif_core.c 中的 btif_enable_bluetooth_evt(tBTA_STATUS status) 回调给应用

1void btif_enable_bluetooth_evt(tBTA_STATUS status){ 2 // 省略代码 3 HAL_CBACK(bt_hal_cbacks, adapter_properties_cb, BT_STATUS_SUCCESS, 1, &prop); 4}

然后回调给 adapter_properties_callback:返回手机蓝牙设备的地址、名称、UUID

adapter_state_change_callback 回调 通过 C调用 Java的代码 callbackEnv->CallVoidMethod(sJniCallbacksObj, method_stateChangeCallback, (jint)status);  返回给应用中的也就是回调java层代码 JniCallback.java文件中stateChangeCallback方法。这时跳转到AdapterState.java中,执行stateChangeCallback()方法;发送了ENABLED_READY消息。根据以上分析,这时状态机还处于PendingCommandState,在该状态下处理ENABLED_READY消息,

1 case ENABLED_READY: 2 removeMessages(ENABLE_TIMEOUT); 3 mPendingCommandState.setBleTurningOn(false); 4 transitionTo(mBleOnState); 5 notifyAdapterStateChange(BluetoothAdapter.STATE_BLE_ON); 6 break;

做下面两个动作:状态切换到mOnState;更新adapterProperties中的蓝牙状态信息;通知蓝牙状态变为打开。具体看下notifyAdapterStateChange方法。主要是调用了adapterService类的方法。

1private void notifyAdapterStateChange(int newState) { 2 AdapterService adapterService = mAdapterService; 3 AdapterProperties adapterProperties = mAdapterProperties; 4 if ((adapterService == null) || (adapterProperties == null)) { 5 errorLog("notifyAdapterStateChange after cleanup:" + newState); 6 return; 7 } 8 9 int oldState = adapterProperties.getState(); 10 adapterProperties.setState(newState); 11 infoLog("Bluetooth adapter state changed: " + oldState + "-> " + newState); 12 adapterService.updateAdapterState(oldState, newState); 13 }

adapterService.updateAdapterState(oldState, newState); 
来到adapterService类。

1 void updateAdapterState(int prevState, int newState){ 2 if (mCallbacks !=null) { 3 int n=mCallbacks.beginBroadcast(); 4 debugLog("updateAdapterState() - Broadcasting state to " + n + " receivers."); 5 for (int i=0; i <n;i++) { 6 try { 7// 完成回调 发送广播给调用者 8 9mCallbacks.getBroadcastItem(i).onBluetoothStateChange(prevState,newState); 10 } catch (RemoteException e) { 11 debugLog("updateAdapterState() - Callback #" + i + " failed (" + e + ")"); 12 } 13 } 14 mCallbacks.finishBroadcast(); 15 } 16 }

之前在打开蓝牙操作初期,在BluetoothManagerService中注册了回调方法,因此又跳转到framework中,执行回调方法。蓝牙打开从framework公共接口开始调用enable方法,执行到bluetooth.apk中,在该应用中通过jni注册回调方法和调用hal层打开蓝牙方法,在驱动层完成蓝牙上电等操作后,通过hal-jni回调到应用层中,应用通过aidl回调通知framework蓝牙状态变化,framework发送广播通知大家蓝牙打开。

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )