您的位置:首页 > 产品设计 > UI/UE

android 4.4 bluetooth 启动分析

2017-03-07 18:11 316 查看
https://my.oschina.net/u/1436933/blog/192060

一. 蓝牙的协议框架

                    
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("ro.kernel.qemu").equals("1")) {

                Slog.i(TAG, "No Bluetooh Service (emulator)");

            } else if (factoryTest == SystemServer.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);

            }

其它进程通过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,"Broadcasting updateAdapterState() to " + n + " receivers.");
           
for (int i=0; i <n;i++) {
               
try {
                   
mCallbacks.getBroadcastItem(i).onBluetoothStateChange(prevState,newState);
               
}  catch (RemoteException e) {
                   
Log.e(TAG, "Unable to call onBluetoothStateChange() on callback #" + i, e);
               
}
           
}
           
mCallbacks.finishBroadcast();
       
}
   
}

mCallbacks该回调是BluetoothManagerService在成功bind到AdapterService时注册的回调mBluetoothCallback:
case
MESSAGE_BLUETOOTH_SERVICE_CONNECTED:
               
{
                   
if (DBG) Log.d(TAG,"MESSAGE_BLUETOOTH_SERVICE_CONNECTED: " + msg.arg1);

                   
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,"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); //注册Adapter状态变更的callback
                       
} catch (RemoteException re) {
                           
Log.e(TAG, "Unable to register BluetoothCallback",re);
                       
}
...

而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, "onBluetoothStateChange: up=" + up);
                   
if (!up) {
                       
if (VDBG) Log.d(TAG,"Unbinding service...");
                       
synchronized (mConnection) {
                           
try {
                               
mService = null;
                               
mContext.unbindService(mConnection);
                           
} catch (Exception re) {
                               
Log.e(TAG,"",re);
                           
}
                       
}
                   
} else {
                       
synchronized (mConnection) {
                           
try {
                               
if (mService == null) {
                                   
if (VDBG) Log.d(TAG,"Binding service...");
                                   
doBind();//绑定到HeadsetService
                               
}
                           
} catch (Exception re) {
                               
Log.e(TAG,"",re);
                           
}
                       
}
                   
}
               
}
       
};

那么既然profile要去bind到对应的service上,这些profile对应的Sercice又是什么时候注册的呢?
这个很关键,其实在我们使能蓝牙过程中,AdapaterStateMachine处于OffState状态,处理
msg.what == USER_TURN_ON
case
USER_TURN_ON:
                  
if (DBG) Log.d(TAG,"CURRENT_STATE=OFF, MESSAGE = USER_TURN_ON");
                  
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("processStart()");
       
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("processStart(): Make Bond State Machine");}
       
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("processStart(): Profile Services alreay started");}
           
mAdapterStateMachine.sendMessage(mAdapterStateMachine.obtainMessage(AdapterState.STARTED));
       
}
   
}

以上就是profiles对应服务的注册。

3)BluetoothManagerService中处理两个callback:一个是来自BluetoothAdapter实例化时注册的回调mManagerCallback并添加到BluetoothManagerService类private
final RemoteCallbackList<IBluetoothManagerCallback> mCallbacks中,该callback主要用于当BluetoothManagerService成功bind到AdapterService时BluetoothDevice获取AdapterService的句柄(BluetoothDevice获取的过程也是向BluetoothAdapter注册回调的机制);另一个来自于各个profile实现类如BluetoothHeadset注册的callback添加到BluetoothManagerService类private
final RemoteCallbackList<IBluetoothStateChangeCallback> mStateChangeCallbacks中,用户通知每个profile adapter状态的变化如TURNING_ON、TURN_ON、TURNING_OFF、TURN_OFF等;

4)Bluetooth中采用的回调机的地方太多,从Settings中显示部分就多处采用回调来更新UI显示,如BluetoothSettings父类DeviceListPreferenceFragment在onResume()时向LocalBluetoothEventManager中注册callback:
@Override
   
public void onResume() {
       
super.onResume();
       
if (mLocalManager == null) return;

       
mLocalManager.setForegroundActivity(getActivity());
       
mLocalManager.getEventManager().registerCallback(this);//注册回调

       
updateProgressUi(mLocalAdapter.isDiscovering());
   
}

不仅如此,在JNI和bluedroid的通信中也采用的时回调机制,如com_android_bluetooth_btservice_AdapterService.cpp类在初始化bluedroid时:
static
bool initNative(JNIEnv* env, jobject obj) {
   
ALOGV("%s:",__FUNCTION__);

   
sJniCallbacksObj = env->NewGlobalRef(env->GetObjectField(obj, sJniCallbacksField));

   
if (sBluetoothInterface) {
       
int ret = sBluetoothInterface->init(&sBluetoothCallbacks);//初始化回调接口
       
if (ret != BT_STATUS_SUCCESS) {
           
ALOGE("Error while setting the callbacks \n");
           
sBluetoothInterface = NULL;
           
return JNI_FALSE;
       
}
       
if ( (sBluetoothSocketInterface = (btsock_interface_t *)
                 
sBluetoothInterface->get_profile_interface(BT_PROFILE_SOCKETS_ID)) == NULL) {
               
ALOGE("Error getting socket interface");
       
}

       
if ( (sBluetoothMceInterface = (btmce_interface_t *)
                 
sBluetoothInterface->get_profile_interface(BT_PROFILE_MAP_CLIENT_ID)) == NULL) {
               
ALOGE("Error getting mapclient interface");
       
} else {
           
if ( (sBluetoothMceInterface->init(&sBluetoothMceCallbacks)) != BT_STATUS_SUCCESS) {
               
ALOGE("Failed to initialize Bluetooth MCE");
               
sBluetoothMceInterface = NULL;
           
}
       
}

       
return JNI_TRUE;
   
}
   
return JNI_FALSE;
}

初次看code时可能会感觉很绕,怎么会那么多回调呀?习惯了就好,这貌似时BRCM代码风格。

4.蓝牙关键类管理流程

                                                   
—— A2dpProfile      < ———— >          BluetoothA2dp       <————>       A2dpService     <—————>    A2dpStateMachine   <————>  
                                                  
|        (注册Listener监听profile的连接状态)          (bind到A2dpService)             (采用状态机管理)                 (jni机制)
                                                    
com_android_bluetooth_a2dp <————> blueDroid <————> HCI
                                                  
|...
                     
—— LocalBluetoothProfile <——>|
                    
|    (管理所有的profiles)      |
                    
|                              —— HidProfile      < ———— >          BluetoothHid       <————>       HidService   <—————> com_android_bluetooth_hid <————> blueDroid <————> HCI
                    
|                                    (注册Listener监听profile的连接状态)         (bind到HidService)               (jni机制)
                    
|                                                                                                                                              —— AdapterStateMachine
LocalBluetoothManager|——
LocalBluetoothApater      <——>     BluetoothAdapter   <————>   BluetoothManagerService <————>          AdapterService           < ————> |                 均通过JniCallback回调
(上层本地蓝牙管理类)|     
(本地Adpater)     (调用远端的实现)                (开启/关闭)   (蓝牙远端服务管理类)          (负责开启/关闭及其它profile服务的管理)        —— BondStateMachine
                    
|
                    
|
                     
—— BluetoothEventManager               <————>                 CachedBluetoothDeviceManager
                                           
(注册广播监听蓝牙状态变更、蓝牙设备状态)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: