一、写在前面的话
近来由于项目需求需要搞蓝牙这一块,之前在上家公司带LC(本地连接)组时也做过一点蓝牙,在Android系统中也解过一些bug,但是不够系统,现在正好比较系统的学习蓝牙。
二、蓝牙的协议框架
A2dp Handset opp Hid Health Pan Map Dun... | | |...
CORE Stack Specification |
Host Controller Interface | chip
三、Android 4.4(Kitkat)上蓝牙的启动流程
1.服务启动
系统启动时在SystemServer中注册蓝牙服务管理BluetoothManagerService服务:
if (SystemProperties.get(\ Slog.i(TAG, \
} else if (factoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) { Slog.i(TAG, \
} else if (!context.getPackageManager().hasSystemFeature (PackageManager.FEATURE_BLUETOOTH)) {
Slog.i(TAG, \ } else if (disableBluetooth) {
Slog.i(TAG, \ } else {
Slog.i(TAG, \
bluetooth = new BluetoothManagerService(context); ServiceManager.addService(BluetoothAdapter.BLUETOOTH_MANAGER_SERVICE, bluetooth); }
其它进程通过binder机制调用该服务,该服务属于综合服务管理类,包括AdapterService的启动、蓝牙适配器Adapter的管理等。
2.蓝牙启动模式
在4.4上蓝牙的启动模式分两种:QuietEnableMode和普通从“设置”里打开两种方式,前一中方式主要是为了NFC的Handover功能——在传递媒体大文件时nfc会打开蓝牙传送。
3.蓝牙关键服务启动和回调处理
下面就以在“设置”中打开为例描述下蓝牙的启动流程:
1)蓝牙所有的profiles位于上层代码中/packages/apps/Bluetooth目录下,常用的几个profiles包括A2dp、HeadSet、Opp、Hid、Pan等,并且Android 4.4上蓝牙协议栈采用的是BRCM和Google共同开发的bluedroid;
2)启动流程涉及代码结构Settings -> Bluetooth -> framework -> bluedroid -> hci -> chip,启动过程是先启动AdapterService并初始化bluedroid,然后启动所有的profile service(A2dpService、HeadsetService等),
成功加载所支持的profiles后使能bluedroid给蓝牙上电,蓝牙上电成功后回bluedroid回调类com_android_bluetooth_btservice_AdapterService.cpp的接口static void adapter_state_change_callback(bt_state_t status),通过JNI回调通知AdapterStateMachine更新Adapter状态,并且通知注册到AdapterService上回调: void updateAdapterState(int prevState, int newState){ if (mCallbacks !=null) {
int n=mCallbacks.beginBroadcast();
Log.d(TAG,\ for (int i=0; i mCallbacks.getBroadcastItem(i).onBluetoothStateChange(prevState,newState); } catch (RemoteException e) { Log.e(TAG, \ } } mCallbacks.finishBroadcast(); } } mCallbacks该回调是BluetoothManagerService在成功bind到AdapterService时注册的回调mBluetoothCallback: case MESSAGE_BLUETOOTH_SERVICE_CONNECTED: { if (DBG) Log.d(TAG,\ mIsBluetoothServiceConnected = true; IBinder service = (IBinder) msg.obj; synchronized(mConnection) { if (msg.arg1 == SERVICE_IBLUETOOTHGATT) { mBluetoothGatt = IBluetoothGatt.Stub.asInterface(service); 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,\ } } catch (RemoteException e) { Log.e(TAG,\ } 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); //注册Adapter状态变更的callback } catch (RemoteException re) { Log.e(TAG, \ } ... 而BluetoothManagerService注册该callback的目的是通知系统所有支持的profiles蓝牙的开启状态,用于更新每个profile和对应profile服务的bind,如通知BluetoothHeadset bind到HeadsetService上,通过binder机制获取HeadsetService的句柄进行相关操作: BluetoothHeadset.java final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback = new IBluetoothStateChangeCallback.Stub() { public void onBluetoothStateChange(boolean up) { if (DBG) Log.d(TAG, \ if (!up) { if (VDBG) Log.d(TAG,\ synchronized (mConnection) { try { mService = null; mContext.unbindService(mConnection); } catch (Exception re) { Log.e(TAG,\ } } } else { synchronized (mConnection) { try { if (mService == null) { if (VDBG) Log.d(TAG,\ doBind();//绑定到HeadsetService } } catch (Exception re) { Log.e(TAG,\ } } } } }; 那么既然profile要去bind到对应的service上,这些profile对应的Sercice又是什么时候注册的呢? 这个很关键,其实在我们使能蓝牙过程中,AdapaterStateMachine处于OffState状态,处理 msg.what == USER_TURN_ON case USER_TURN_ON: if (DBG) Log.d(TAG,\ notifyAdapterStateChange(BluetoothAdapter.STATE_TURNING_ON); mPendingCommandState.setTurningOn(true); transitionTo(mPendingCommandState); sendMessageDelayed(START_TIMEOUT, START_TIMEOUT_DELAY); adapterService.processStart();//启动系统支持的所有profiles的services 对应调用AdapterService的接口: void processStart() { if (DBG) debugLog(\ Class[] supportedProfileServices = Config.getSupportedProfiles(); //Initialize data objects for (int i=0; i < supportedProfileServices.length;i++) { mProfileServicesState.put(supportedProfileServices[i].getName(),BluetoothAdapter.STATE_OFF); } mRemoteDevices = new RemoteDevices(mPowerManager, this); mAdapterProperties.init(mRemoteDevices); if (DBG) {debugLog(\ mBondStateMachine = BondStateMachine.make(this, mAdapterProperties, mRemoteDevices); mJniCallbacks.init(mBondStateMachine,mRemoteDevices); //FIXME: Set static instance here??? setAdapterService(this); //Start profile services if (!mProfilesStarted && supportedProfileServices.length >0) { //Startup all profile services setProfileServiceState(supportedProfileServices,BluetoothAdapter.STATE_ON); }else { if (DBG) {debugLog(\ mAdapterStateMachine.sendMessage(mAdapterStateMachine.obtainMessage(AdapterState.STARTED)); } } 以上就是profiles对应服务的注册。 3)BluetoothManagerService中处理两个callback:一个是来自BluetoothAdapter实例化时注册的回调mManagerCallback并添加到BluetoothManagerService类private final RemoteCallbackList 4)Bluetooth中采用的回调机的地方太多,从Settings中显示部分就多处采用回调来更新UI显示,如BluetoothSettings父类DeviceListPreferenceFragment在onResume()时向LocalBluetoothEventManager中注册callback: @Override public void onResume() { super.onResume(); if (mLocalManager == null) return;