【Android4.4蓝牙代码分析】- 蓝牙Enable过程
来源:互联网 发布:大唐软件校园招聘 编辑:程序博客网 时间:2024/06/06 01:54
【Android4.4蓝牙代码分析】- 蓝牙Enable过程
(一)基本说明
本文的代码选用的是Android4.4的kitkat代码。
本文是在Windows环境下通过source insight进行代码阅读,所以大部分目录是以windows的目录结构以’\’区分层级关系。
(二)搭建代码环境
首先介绍下本文source insight所加载的代码路径,bluedroid代码结构可以参考BlueDroid概述。
- package/apps/Bluetooth,这个目录下是Bluetooth的app源码。
- hardware/libhardware/include/hardware,JNI层的一些代码。
- external/Bluetooth/bluedroid,bluedroid协议栈代码。
- frameworks\base\core\java\android\bluetooth,framework层的java代码与aidl文件。
- packages\apps\Settings\src\com\android\settings\bluetooth,Setting App源码中的bluetooth代码
- frameworks\base\services\java\com\android\server,系统核心服务的代码,系统启动后会在这注册蓝牙服务。
(三)蓝牙enable好文分享
有关于Android bluedroid的enable分析已经有很多大牛分析了,现在分享出部分好的博客,本文很多东西都是参考他们的文章。
- Android BlueDroid(三):BlueDroid蓝牙开启过程enable,该文给出了总体的流程图,在总体结构上对蓝牙enable过程可以有个清晰的认识。
- Android 4.2 Bluetooth 分析总结(二) 蓝牙enable 的整个过程,该文给出了log,并且按照代码运行流程一个个函数的进行分析,本文很多内容都参考至该文。
- android bluetooth 移植相关注意事项,该文将了下蓝牙移植的相关知识,在进行代码阅读之前看看该文,能够从一个总体层次上对bluedroid代码进行分析。
- android – 蓝牙 bluetooth (二) 打开蓝牙,该文是也很不错,作者最开始就是看的该博客。
(四)代码分析
在Android系统启动过程中,其会首先加载SystemServer.java,System Server是Android系统的核心,他在Dalvik虚拟机启动后立即开始初始化和运行。其它的系统服务在System Server进程的环境中运行。在Android系统开机过程中,蓝牙服务也会在这里注册,并运行,关于SystemServer.java详见(Android的System Server),这样蓝牙服务进程就作为一个线程运行在SystemServer进程中。最后一个else分支是我们所关心的,通过ServiceManager.addService方法向ServiceManager进程中注册了蓝牙服务,后面要使用时只需要通过getService(BluetoothAdapter.BLUETOOTH_MANAGER_SERVICE)
方法即可(BluetoothAdapter类在frameworks\base\core\java\android\bluetooth目录下,BLUETOOTH_MANAGER_SERVICE值为“bluetooth_manager”)。
代码位置:frameworks\base\services\java\com\android\server\SystemServer.java
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); }
我们先看一下BluetoothManagerService类的构造函数,代码比较多,我们主要看两个地方,loadStoredNameAndAddress()
是读取蓝牙打开默认名称的地方,isBluetoothPersistedStateOn()
是用来判断蓝牙是否已打开的,如果已打开,需要执行开启蓝牙的动作,前几行注册的广播其中就有这个作用。
代码位置:frameworks\base\services\java\com\android\server\BluetoothManagerService.java
BluetoothManagerService(Context context) { …一些变量声明初始化… IntentFilter filter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED); filter.addAction(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED); filter.addAction(Intent.ACTION_USER_SWITCHED); registerForAirplaneMode(filter); mContext.registerReceiver(mReceiver, filter); loadStoredNameAndAddress(); if (isBluetoothPersistedStateOn()) { mEnableExternal = true; } }
上面就完成了蓝牙的系统服务注册工作,如果没有设置蓝牙打开,系统也不会打开蓝牙,后面如果需要用到蓝牙服务只需通过systemServer的getServer方法即可。
现在回到用户真正能接触到的界面开关部分,蓝牙界面开关就是Setting界面中的蓝牙开关,其实际就是调用BluetoothEnabler.java这个类了,BluetoothEnabler类是实现 CompoundButton.OnCheckedChangeListener
按键监听器,看到其onCheckedChanged方法,当按键按下时会跳入该方法,在该方法中首先判断是否开启了飞行模式,如果没则调用mLocalAdapter(LocalBluetoothAdapter)的setBluetoothEnabled()
方法,执行具体的开关动作。
代码位置:packages\apps\Settings\src\com\android\settings\bluetooth\BluetoothEnabler.java
public final class BluetoothEnabler implements CompoundButton.OnCheckedChangeListener { public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { // Show toast message if Bluetooth is not allowed in airplane mode if (isChecked && !WirelessSettings.isRadioAllowed(mContext, Settings.Global.RADIO_BLUETOOTH)) { Toast.makeText(mContext, R.string.wifi_in_airplane_mode, Toast.LENGTH_SHORT).show(); // Reset switch to off buttonView.setChecked(false); } if (mLocalAdapter != null) { mLocalAdapter.setBluetoothEnabled(isChecked); } mSwitch.setEnabled(false); } }
在LocalBluetoothAdapter类的setBluetoothEnabled方法中,根据是否打开再调用mAdapter(BluetoothAdapter)的enable或disable方法。并更新蓝牙状态机。
代码位置:packages\apps\Settings\src\com\android\settings\bluetooth\LocalBluetoothAdapter.java
public void setBluetoothEnabled(boolean enabled) { boolean success = enabled ? mAdapter.enable() : mAdapter.disable(); if (success) { setBluetoothStateInt(enabled ? BluetoothAdapter.STATE_TURNING_ON : BluetoothAdapter.STATE_TURNING_OFF); } else { if (Utils.V) { Log.v(TAG, "setBluetoothEnabled call, manager didn't return " +"success for enabled: " + enabled); } syncBluetoothState(); } }
请注意:这时候代码已经跳转到了framework层了。
在BluetoothAdapter类中可以看到一个单例模式的应用,主要提供给其它程序调用蓝牙的一些方法用的,外部程序想调用蓝牙的方法就要先用这个拿到BluetoothAdapter对象,代码也简单看下吧,里面是典型的binder应用。就是前面在SystemServer中注册的蓝牙服务。
代码位置:frameworks\base\core\java\android\bluetooth\BluetoothAdapter.java
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; }
此时我们更关心mAdapter.enable()
的后续操作,外部其它应用到getDefaultAdapter()也是调用enable(),注意,到了BluetoothAdapter我们已经在framework层了,顺着BluetoothAdapter.java的enable()调用,其先判断蓝牙是否已经打开,如果没打开则调用mManagerService(IBluetoothManager)的enable方法。
代码位置:frameworks\base\core\java\android\bluetooth\BluetoothAdapter.java
public boolean enable() { if (isEnabled() == true){ if (DBG) Log.d(TAG, "enable(): BT is already enabled..!"); return true; } try { return mManagerService.enable(); } catch (RemoteException e) {Log.e(TAG, "", e);} return false; }
IBluetoothManager类是Android进程间通信的接口,在其中定义了一堆的接口,一般这种远程服务对应的类名就是 BluetoothManagerService 类,主要用于调用在SystemServer中注册的蓝牙服务。在BluetoothAdapter类的构造函数中,将mManagerService绑定到了ServiceManager.getService(BLUETOOTH_MANAGER_SERVICE)
的蓝牙服务中。我们直接进入BluetoothManagerService类的enable()方法。
代码位置:frameworks\base\core\java\android\bluetooth\BluetoothAdapter.java
interface IBluetoothManager { IBluetooth registerAdapter(in IBluetoothManagerCallback callback); void unregisterAdapter(in IBluetoothManagerCallback callback); void registerStateChangeCallback(in IBluetoothStateChangeCallback callback); void unregisterStateChangeCallback(in IBluetoothStateChangeCallback callback); boolean isEnabled(); boolean enable(); boolean enableNoAutoConnect(); boolean disable(boolean persist); IBluetoothGatt getBluetoothGatt(); String getAddress(); String getName(); }
在BluetoothManagerService类的enable()方法中,第一个if看到log那就知道如果enable正常就不会走,第二个if是打印调试信息,在后面的synchronized函数体中,实际有用的是sendEnableMsg(false)
方法,跳到sendEnableMsg中。
代码位置:frameworks\base\services\java\com\android\server\BluetoothManagerService.java
public boolean enable() { if ((Binder.getCallingUid() != Process.SYSTEM_UID) && (!checkIfCallerIsForegroundUser())) { Log.w(TAG,"enable(): not allowed for non-active and non system user"); return false; } mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); if (DBG) { Log.d(TAG,"enable(): mBluetooth =" + mBluetooth + " mBinding = " + mBinding); } synchronized(mReceiver) { mQuietEnableExternal = false; mEnableExternal = true; // waive WRITE_SECURE_SETTINGS permission check long callingIdentity = Binder.clearCallingIdentity(); persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH); Binder.restoreCallingIdentity(callingIdentity); sendEnableMsg(false); } return true; }
可以看到在sendEnableMsg中向系统发送了一条MESSAGE_ENABLE
消息,再跳转到mHandler(BluetoothHandler)类的handleMessage方法,可以看到在handleMessage
中有对MESSAGE_ENABLE
消息的处理函数,实际的话就是调用了BluetoothManagerService类的handleEnable方法。
代码位置:frameworks\base\services\java\com\android\server\BluetoothManagerService.java
private class BluetoothHandler extends Handler { ... @Override public void handleMessage(Message msg) { if (DBG) Log.d (TAG, "Message: " + msg.what); switch (msg.what) { case MESSAGE_ENABLE: if (DBG) { Log.d(TAG, "MESSAGE_ENABLE: mBluetooth = " + mBluetooth); } mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE); mEnable = true; handleEnable(msg.arg1 == 1); break; } } } }
handleEnable方法比较长,看到注释说明//Enable bluetooth,我们直接看这部分代码,实际执行的是mBluetooth.enable()
,又是一个接口IBluetooth。
代码位置:frameworks\base\services\java\com\android\server\BluetoothManagerService.java
private void handleEnable(boolean quietMode) { mQuietEnable = quietMode; synchronized(mConnection) { if ((mBluetooth == null) && (!mBinding)) { //Start bind timeout and bind Message timeoutMsg=mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND); mHandler.sendMessageDelayed(timeoutMsg,TIMEOUT_BIND_MS); mConnection.setGetNameAddressOnly(false); Intent i = new Intent(IBluetooth.class.getName()); if (!doBind(i, mConnection,Context.BIND_AUTO_CREATE, UserHandle.CURRENT)) { mHandler.removeMessages(MESSAGE_TIMEOUT_BIND); } else { mBinding = true; } } else if (mBluetooth != null) { if (mConnection.isGetNameAddressOnly()) { // if GetNameAddressOnly is set, we can clear this flag, // so the service won't be unbind // after name and address are saved 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(); } //Enable bluetooth try { if (!mQuietEnable) { 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); } } } }
mBluetooth(IBluetooth)这个接口到底是对应哪个远程服务呢?在同一个目录下搜索,先搜索mBluetooth在哪里赋值了,搜索完BluetoothManagerService.java只在handleMessage
中找到了mBluetooth = IBluetooth.Stub.asInterface(service)
,而IBinder service = (IBinder) msg.obj
。也就是远程服务是发送“MESSAGE_BLUETOOTH_SERVICE_CONNECTED”消息对象。继续在BluetoothManagerService类中搜索是谁发送这条消息。
代码位置:frameworks\base\services\java\com\android\server\BluetoothManagerService.java
private class BluetoothHandler extends Handler { ... @Override public void handleMessage(Message msg) { if (DBG) Log.d (TAG, "Message: " + msg.what); switch (msg.what) { 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); break; } // else must be SERVICE_IBLUETOOTH //Remove timeout mHandler.removeMessages(MESSAGE_TIMEOUT_BIND); mBinding = false; mBluetooth = IBluetooth.Stub.asInterface(service); ... break; } } } }
在BluetoothManagerService.java中发现在onServiceConnected方法中构建了该消息,并将调用该方法的service赋值给msg.obj
,到底谁调用了这个函数呢,尝试搜索了下“onServiceConnected”并没有得到想要的结果,再回到onServiceConnected方法中,可以看到有个log,"BluetoothServiceConnection: " + className.getClassName()
,就是说将BluetoothServiceConnection连接到一个服务上,在看到下面的if判断,最有可能的是连接到了AdapterService
服务中。在Android 4.2 Bluetooth 分析总结(二) 蓝牙enable 的整个过程中作者从实际打印的log中也指出了在这一步系统会跳转到AdapterService。 D/BluetoothManagerService( 1646): BluetoothServiceConnection: connected to AdapterService
代码位置:frameworks\base\services\java\com\android\server\BluetoothManagerService.java
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); }
这时代码从framework层跳到了APP层,符合了android代码架构图中的定义。
我们看到AdapterService的enable方法,可以发现在AdapterService类中有三个enable函数,从framework层到这到底调用了哪个enable函数呢,根据代码注释和实际情况,应该是调用了在AdapterServiceBinder
类中的enable方法,在该方法中调用了service.enable()
,而service是通过getService()
方法获取的,看到该方法,实际是返回了mService(AdapterService)
,也就是调用了boolean enable()
方法,最终调用了public synchronized boolean enable(boolean quietMode)
方法。在这个方法中主要是构建了一个AdapterState.USER_TURN_ON消息,并发送给状态机mAdapterStateMachine
去处理。
代码位置:packages\apps\Bluetooth\src\com\android\bluetooth\btservice\AdapterService.java
public class AdapterService extends Service { ... private static class AdapterServiceBinder extends IBluetooth.Stub { private AdapterService mService; public AdapterServiceBinder(AdapterService svc) { mService = svc; } ... public boolean enable() { if ((Binder.getCallingUid() != Process.SYSTEM_UID) && (!Utils.checkCaller())) { Log.w(TAG,"enable(): not allowed for non-active user and non system user"); return false; } AdapterService service = getService(); if (service == null) return false; return service.enable(); } ... public AdapterService getService() { if (mService != null && mService.isAvailable()) { return mService; } return null; } } ... //----API Methods-------- ... boolean enable() { return enable (false); } ... public synchronized boolean enable(boolean quietMode) { enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); if (DBG)debugLog("Enable called with quiet mode status = " + mQuietmode); mQuietmode = quietMode; Message m = mAdapterStateMachine.obtainMessage(AdapterState.USER_TURN_ON); mAdapterStateMachine.sendMessage(m); return true; } }
这里用到了状态机的概念,在网上查了下有关Android蓝牙状态机的资料,没有找到合适的,大多是Android4.2之前的状态机分析,通过查看源码,在AdapterState状态机的注释中可以发现如下说明,说明该状态机有三个状态,分别是OnState、OffState以及PendingCommandState,再根据注释,在初始状态下,蓝牙应该处于OffState,中间态是PendingCommandState,正在打开是OnState。具体没有深入去分析代码,可能有错误,暂时按照这个流程继续进行蓝牙enable分析。
代码位置:packages\apps\Bluetooth\src\com\android\bluetooth\btservice\AdapterState.java
/** * This state machine handles Bluetooth Adapter State. * States: * {@link OnState} : Bluetooth is on at this state * {@link OffState}: Bluetooth is off at this state. This is the initial * state. * {@link PendingCommandState} : An enable / disable operation is pending. * TODO(BT): Add per process on state. */
我们重点看状态机的消息处理部分,由于这时候进行的是蓝牙开启操作,状态机处于OffState状态下,在OffState的processMessage
中找到对USER_TURN_ON
的处理函数,前面的几个是进行状态机的状态更新,最后调用了adapterService.processStart()
,我们跳进去看。
代码位置:packages\apps\Bluetooth\src\com\android\bluetooth\btservice\AdapterState.java
final class AdapterState extends StateMachine { ... private class OffState extends State { ... @Override public boolean processMessage(Message msg) { AdapterService adapterService = mAdapterService; if (adapterService == null) { Log.e(TAG,"receive message at OffState after cleanup:" + msg.what); return false; } switch(msg.what) { 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(); break; ... } return true; } } ... }
又回到了AdapterService,通过看给出的log提示以及函数名称,大概是进行了所有profile的状态机状态开启设置,在最后一个else中的log中也是显示processStart(): Profile Services alreay started
,最后又调用状态机执行AdapterState.STARTED
消息,执行mAdapterStateMachine.sendMessage(mAdapterStateMachine.obtainMessage(AdapterState.STARTED))
。
代码位置:packages\apps\Bluetooth\src\com\android\bluetooth\btservice\AdapterService.java
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(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)); } }
再次回到AdapterState类,由于这时候状态机处于pending状态下,所以在PendingCommandState
中对该消息进行处理,实际是调用了adapterService.enableNative()
方法,也就是终于通过JNI开始向下层调用底层操作方法进行蓝牙Enable操作。
代码位置:packages\apps\Bluetooth\src\com\android\bluetooth\btservice\AdapterState.java
final class AdapterState extends StateMachine { ... private class PendingCommandState extends State { private boolean mIsTurningOn; private boolean mIsTurningOff; ... @Override public boolean processMessage(Message msg) { ... switch(msg.what) { case STARTED: if (DBG) Log.d(TAG,"CURRENT_STATE=PENDING, MESSAGE = STARTED, isTurningOn=" + isTurningOn + ", isTurningOff=" + isTurningOff); //Remove start timeout removeMessages(START_TIMEOUT); //Enable boolean ret = adapterService.enableNative(); if (!ret) { Log.e(TAG, "Error while turning Bluetooth On"); notifyAdapterStateChange(BluetoothAdapter.STATE_OFF); transitionTo(mOffState); } else { sendMessageDelayed(ENABLE_TIMEOUT, ENABLE_TIMEOUT_DELAY); } break; ... } return true; } } ... }
这里已经通过JNI从APP framework层进入了bluedroid协议栈了。
根据Android JNI层的命名规则,找到了com_android_bluetooth_btservice_AdapterService.cpp
,看到其中的enableNative()
方法。实际是调用了sBluetoothInterface(bt_interface_t)
的enable方法。sBluetoothInterface这个又是一个接口,在网上看别人写的博客说不能跳转,但是我这边可以直接跳转到bt_interface_t
的定义,如果不能跳转依然可以到这个文章中看如何跳转Android 4.2 Bluetooth 分析总结(二) 蓝牙enable 的整个过程。
代码位置:packages\apps\Bluetooth\jni\com_android_bluetooth_btservice_AdapterService.cpp
static jboolean enableNative(JNIEnv* env, jobject obj) { ALOGV("%s:",__FUNCTION__); jboolean result = JNI_FALSE; if (!sBluetoothInterface) return result; int ret = sBluetoothInterface->enable(); result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; return result; }
可以看出,在这个结构体中包含了大量的接口,有bluetooth.h自然有bluetooth.c文件,我们跳转到bluetooth.c中看下接口的具体实现。
代码位置:hardware\libhardware\include\hardware\bluetooth.h
/** Represents the standard Bluetooth DM interface. */ typedef struct { /** set to sizeof(bt_interface_t) */ size_t size; /** * Opens the interface and provides the callback routines * to the implemenation of this interface. */ int (*init)(bt_callbacks_t* callbacks ); /** Enable Bluetooth. */ int (*enable)(void); /** Disable Bluetooth. */ int (*disable)(void); ... } bt_interface_t;
终于开始了最喜欢的c代码了,c代码看起来就轻松多了。
在这里可以看到bluetooth.c实例化了一个bt_interface_t
对象,bluetoothInterface。跳转到enable函数中,在打印了一个log信息后,先会对接口进行检查,如果接口ready就调用btif_enable_bluetooth()
方法。
代码位置:external\bluetooth\bluedroid\btif\src\bluetooth.c
static int enable( void ) { ALOGI("enable"); /* sanity check */ if (interface_ready() == FALSE) return BT_STATUS_NOT_READY; return btif_enable_bluetooth(); } ... static const bt_interface_t bluetoothInterface = { sizeof(bluetoothInterface), init, enable, disable, cleanup, get_adapter_properties, get_adapter_property, set_adapter_property, get_remote_device_properties, get_remote_device_property, set_remote_device_property, get_remote_service_record, get_remote_services, start_discovery, cancel_discovery, create_bond, remove_bond, cancel_bond, pin_reply, ssp_reply, get_profile_interface, dut_mode_configure, dut_mode_send, #if BLE_INCLUDED == TRUE le_test_mode, #else NULL, #endif config_hci_snoop_log };
到了这一步基本上已经完成了上层的一堆蓝牙Enable代码分析,后面的都是bluedroid的代码了,具体到蓝牙的实际开关又涉及到各个厂商Vendor的设计。下面简要写一些后续的蓝牙Enable过程。
一下就跳转到了btif_core.c中了,前面是一堆的判断以及状态机的设置,我们直接看到后面,又调用了bte_main_enable()
,跳进去继续看。
代码位置:external\bluetooth\bluedroid\btif\src\btif_core.c
bt_status_t btif_enable_bluetooth(void) { BTIF_TRACE_DEBUG0("BTIF ENABLE BLUETOOTH"); if (btif_core_state != BTIF_CORE_STATE_DISABLED) { ALOGD("not disabled\n"); return BT_STATUS_DONE; } btif_core_state = BTIF_CORE_STATE_ENABLING; /* Create the GKI tasks and run them */ bte_main_enable(); return BT_STATUS_SUCCESS; }
认真看下这个函数,首先初始化了BTE的控制块,是什么呢,大概看了下,主要是一些参数设置。主要看到bte_hci_enable()
,这个函数比较长,首先启动了一个preload定时器,主要用于重新打开蓝牙的操作,以防蓝牙长时间没有打开,先不管,继续往下看,bt_hc_if(bt_hc_interface_t)
是什么东西呢,我们跳进去看看,bte_hci_enable()
的分析后面继续开展,先看看bt_hc_if(bt_hc_interface_t)
是什么东西,后面很多地方都有调用。
代码位置:external\bluetooth\bluedroid\main\bte_main.c
void bte_main_enable() { APPL_TRACE_DEBUG1("%s", __FUNCTION__); /* Initialize BTE control block */ BTE_Init(); lpm_enabled = FALSE; bte_hci_enable(); GKI_create_task((TASKPTR)btu_task, BTU_TASK, BTE_BTU_TASK_STR, (UINT16 *) ((UINT8 *)bte_btu_stack + BTE_BTU_STACK_SIZE), sizeof(bte_btu_stack)); GKI_run(0); } ... static void bte_hci_enable(void) { APPL_TRACE_DEBUG1("%s", __FUNCTION__); preload_start_wait_timer(); if (bt_hc_if) { int result = bt_hc_if->init(&hc_callbacks, btif_local_bd_addr.address); APPL_TRACE_EVENT1("libbt-hci init returns %d", result); assert(result == BT_HC_STATUS_SUCCESS); if (hci_logging_enabled == TRUE || hci_logging_config == TRUE) bt_hc_if->logging(BT_HC_LOGGING_ON, hci_logfile); #if (defined (BT_CLEAN_TURN_ON_DISABLED) && BT_CLEAN_TURN_ON_DISABLED == TRUE) APPL_TRACE_DEBUG1("%s Not Turninig Off the BT before Turninig ON", __FUNCTION__); /* Do not power off the chip before powering on if BT_CLEAN_TURN_ON_DISABLED flag is defined and set to TRUE to avoid below mentioned issue. Wingray kernel driver maintains a combined counter to keep track of BT-Wifi state. Invoking set_power(BT_HC_CHIP_PWR_OFF) when the BT is already in OFF state causes this counter to be incorrectly decremented and results in undesired behavior of the chip. This is only a workaround and when the issue is fixed in the kernel this work around should be removed. */ #else /* toggle chip power to ensure we will reset chip in case a previous stack shutdown wasn't completed gracefully */ bt_hc_if->set_power(BT_HC_CHIP_PWR_OFF); #endif bt_hc_if->set_power(BT_HC_CHIP_PWR_ON); bt_hc_if->preload(NULL); } }
bt_hc_interface_t
和前面的bt_interface_t
接口一样,根据其说明文件,其是Bluetooth Host/Controller Interface。这个接口的实现在哪呢,看到目录,我们在src目录找找,也可以对整个project进行检索,很快我们发现了对该接口的实现。
代码位置:external\bluetooth\bluedroid\hci\include\bt_hci_lib.h
/* * Bluetooth Host/Controller Interface */ typedef struct { /** Set to sizeof(bt_hc_interface_t) */ size_t size; /** * Opens the interface and provides the callback routines * to the implemenation of this interface. */ int (*init)(const bt_hc_callbacks_t* p_cb, unsigned char *local_bdaddr); /** Chip power control */ void (*set_power)(bt_hc_chip_power_state_t state); /** Set low power mode wake */ int (*lpm)(bt_hc_low_power_event_t event); /** Called prior to stack initialization */ void (*preload)(TRANSAC transac); /** Called post stack initialization */ void (*postload)(TRANSAC transac); /** Transmit buffer */ int (*transmit_buf)(TRANSAC transac, char *p_buf, int len); /** Controls receive flow */ int (*set_rxflow)(bt_rx_flow_state_t state); /** Controls HCI logging on/off */ int (*logging)(bt_hc_logging_state_t state, char *p_path); /** Closes the interface */ void (*cleanup)( void ); } bt_hc_interface_t;
bt_hc_interface_t
接口在bt_hci_bdroid.c
中有具体实现,现在再次回到bte_hci_enable()
。
代码位置:external\bluetooth\bluedroid\hci\src\bt_hci_bdroid.c
static const bt_hc_interface_t bluetoothHCLibInterface = { sizeof(bt_hc_interface_t), init, set_power, lpm, preload, postload, transmit_buf, set_rxflow, logging, cleanup };
首先调用了bt_hc_if
的init函数,根据注释,init函数主要用来打开interface并且提供回调机制,我们跳进去看下。
代码位置:external\bluetooth\bluedroid\main\bte_main.c
static void bte_hci_enable(void) { APPL_TRACE_DEBUG1("%s", __FUNCTION__); preload_start_wait_timer(); if (bt_hc_if) { int result = bt_hc_if->init(&hc_callbacks, btif_local_bd_addr.address); APPL_TRACE_EVENT1("libbt-hci init returns %d", result); assert(result == BT_HC_STATUS_SUCCESS); if (hci_logging_enabled == TRUE || hci_logging_config == TRUE) bt_hc_if->logging(BT_HC_LOGGING_ON, hci_logfile); #if (defined (BT_CLEAN_TURN_ON_DISABLED) && BT_CLEAN_TURN_ON_DISABLED == TRUE) APPL_TRACE_DEBUG1("%s Not Turninig Off the BT before Turninig ON", __FUNCTION__); /* Do not power off the chip before powering on if BT_CLEAN_TURN_ON_DISABLED flag is defined and set to TRUE to avoid below mentioned issue. Wingray kernel driver maintains a combined counter to keep track of BT-Wifi state. Invoking set_power(BT_HC_CHIP_PWR_OFF) when the BT is already in OFF state causes this counter to be incorrectly decremented and results in undesired behavior of the chip. This is only a workaround and when the issue is fixed in the kernel this work around should be removed. */ #else /* toggle chip power to ensure we will reset chip in case a previous stack shutdown wasn't completed gracefully */ bt_hc_if->set_power(BT_HC_CHIP_PWR_OFF); #endif bt_hc_if->set_power(BT_HC_CHIP_PWR_ON); bt_hc_if->preload(NULL); } }
我们都知道,蓝牙的话分为Host和Controller,两者通过HCI层进行数据交互。Host的话是Android操作系统,这部分是通用的,由google公司提供;Controller的话是一个个芯片厂商提供的,这部分各个厂商都有其独立设计。在Android4.2后的bluedroid中将所有厂商的设计文件放在vendor目录中,而为了实现上层对芯片的操作,bluedroid提供了专门的接口,下面我们通过代码分析来了解bluedroid是怎么完成这些操作的。
这个init函数非常的长,首先看到第一个重要跳转就是init_vnd_if(local_bdaddr)
,从函数的字面理解就是调用厂商vender的init函数,在函数的注释中了解到这个函数主要完成vendor lib interface的初始化操作。
代码位置:external\bluetooth\bluedroid\hci\src\bt_hci_bdroid.c
static int init(const bt_hc_callbacks_t* p_cb, unsigned char *local_bdaddr) { ... /* store reference to user callbacks */ bt_hc_cbacks = (bt_hc_callbacks_t *) p_cb; init_vnd_if(local_bdaddr); ... }
在这里完成了厂商定制功能与Android系统的绑定,系统后面都可以通过
bt_vnd_if
调用厂商的定制功能。在这里我们不深入分析厂商具体做了什么。
首先利用dlopen方法打开了libbt-vendor.so厂商的配置文件,并将动态库的句柄赋给dlhandle,再通过dlsym方法将"BLUETOOTH_VENDOR_LIB_INTERFACE"
句柄返回给bt_vnd_if
,关于libbt-vendor.so的介绍说明可以看android bluetooth 移植相关注意事项。在这里主要就是要厂商实现bt_vendor_interface_t
这一通用接口,并且将接口赋值给bt_vnd_if
,后面就可以通过bt_vnd_if
实现对厂商定制功能的调用。最后再利用厂商实现的init方法实现蓝牙芯片的init操作(厂商具体决定init过程的具体操作)。
代码位置:external\bluetooth\bluedroid\hci\src\bt_hw.c
void init_vnd_if(unsigned char *local_bdaddr) { void *dlhandle; dlhandle = dlopen("libbt-vendor.so", RTLD_NOW); if (!dlhandle) { ALOGE("!!! Failed to load libbt-vendor.so !!!"); return; } bt_vnd_if = (bt_vendor_interface_t *) dlsym(dlhandle, "BLUETOOTH_VENDOR_LIB_INTERFACE"); if (!bt_vnd_if) { ALOGE("!!! Failed to get bt vendor interface !!!"); return; } bt_vnd_if->init(&vnd_callbacks, local_bdaddr); }
bt_vendor_lib.h
的定义如下,可以看到dlsym
方法返回的bt_vnd_if
就是指向了bt_vendor_interface_t
结构体。
代码位置:external\bluetooth\bluedroid\hci\include\bt_vendor_lib.h
/* * Bluetooth Host/Controller VENDOR Interface */ typedef struct { /** Set to sizeof(bt_vndor_interface_t) */ size_t size; /* * Functions need to be implemented in Vendor libray (libbt-vendor.so). */ /** * Caller will open the interface and pass in the callback routines * to the implemenation of this interface. */ int (*init)(const bt_vendor_callbacks_t* p_cb, unsigned char *local_bdaddr); /** Vendor specific operations */ int (*op)(bt_vendor_opcode_t opcode, void *param); /** Closes the interface */ void (*cleanup)(void); } bt_vendor_interface_t; /* * External shared lib functions/data */ /* Entry point of DLib -- * Vendor library needs to implement the body of bt_vendor_interface_t * structure and uses the below name as the variable name. HCI library * will use this symbol name to get address of the object through the * dlsym call. */ extern const bt_vendor_interface_t BLUETOOTH_VENDOR_LIB_INTERFACE;
回到bt_hci_bdroid.c
函数,在init_vnd_if
方法中注册了厂商的hci接口,utils_init()
初始化了一个互斥锁,暂不去管他,后面用到了#ifdef…#else…#endif的宏if语句,默认情况下,Android bluedroid是采用h4也就是uart传输方式,也就是其声明了一个hci_h4_func_table
函数体,并将p_hci_if
指向了该函数体,随后调用了hci_h4_func_table
中的init函数。
代码位置:external\bluetooth\bluedroid\hci\src\bt_hci_bdroid.c
static int init(const bt_hc_callbacks_t* p_cb, unsigned char *local_bdaddr) { ... init_vnd_if(local_bdaddr); utils_init(); #ifdef HCI_USE_MCT extern tHCI_IF hci_mct_func_table; p_hci_if = &hci_mct_func_table; #else extern tHCI_IF hci_h4_func_table; p_hci_if = &hci_h4_func_table; #endif p_hci_if->init(); ... }
我们跳到hci_h4_func_table
函数体重看看其具体干了什么,可以看到其定义了一个h4的服务接口,在hci_h4_init
函数中奇首先初始化了一个队列h4_cb.acl_rx_q
用于接收acl数据。然后设置了一些参数,最后init了btsnoop,也就是初始化了抓取蓝牙hci log的btsnoop,实际就是初始化了一个thread,具体就不跳进去了,代码在external\bluetooth\bluedroid\hci\src\btsnoop.c
。
代码位置:external\bluetooth\bluedroid\hci\src\hci_h4.c
void hci_h4_init(void) { HCIDBG("hci_h4_init"); memset(&h4_cb, 0, sizeof(tHCI_H4_CB)); utils_queue_init(&(h4_cb.acl_rx_q)); /* Per HCI spec., always starts with 1 */ num_hci_cmd_pkts = 1; /* Give an initial values of Host Controller's ACL data packet length * Will update with an internal HCI(_LE)_Read_Buffer_Size request */ h4_cb.hc_acl_data_size = 1021; h4_cb.hc_ble_acl_data_size = 27; btsnoop_init(); } /****************************************************************************** ** HCI H4 Services interface table ******************************************************************************/ const tHCI_IF hci_h4_func_table = { hci_h4_init, hci_h4_cleanup, hci_h4_send_msg, hci_h4_send_int_cmd, hci_h4_get_acl_data_length, hci_h4_receive_msg };
bt_hc_worker_thread线程里面有很多重要的事件处理,可以具体看看。
再次回到bt_hci_bdroid.c
函数,在初始化hci后,其继续初始化了userial,也就是初始化了串口,这里需要根据前面的#ifdef来决定跳转到那个userial.c文件,文件位置在external\bluetooth\bluedroid\hci\src\userial.c
。随后对lpm进行了初始化,在lpm_init
函数中调用了芯片厂商中BT_VND_OP_GET_LPM_IDLE_TIMEOUT
所对应的函数,然后赋值给bt_lpm_cb.timeout_ms
,文件位置在external\bluetooth\bluedroid\hci\src\lmp.c
。在utils_queue_init
初始化了一个发送队列。在init函数最后创建了一个bt_hc_worker_thread
蓝牙工作主线程,用于发送和接收命令。
代码位置:external\bluetooth\bluedroid\hci\src\bt_hci_bdroid.c
static int init(const bt_hc_callbacks_t* p_cb, unsigned char *local_bdaddr) { ... p_hci_if->init(); userial_init(); lpm_init(); utils_queue_init(&tx_q); ... pthread_mutex_init(&hc_cb.mutex, NULL); pthread_cond_init(&hc_cb.cond, NULL); pthread_attr_init(&thread_attr); if (pthread_create(&hc_cb.worker_thread, &thread_attr, \ bt_hc_worker_thread, NULL) != 0) { ... } ... return BT_HC_STATUS_SUCCESS; }
回到最初的bte_hci_enable()
函数,上面就完成了bt_hc_if->init
函数,然后根据是否需要打开hci log来打开hci log,后面的宏if语句用于判断是否已经打开蓝牙,如果没有则先关闭chip power bt_hc_if->set_power(BT_HC_CHIP_PWR_OFF)
然后再打开chip power bt_hc_if->set_power(BT_HC_CHIP_PWR_ON)
。最后调用了bt_hc_if->preload(NULL)
函数,主要进行一些芯片的预操作,具体分析见后文。
代码位置:external\bluetooth\bluedroid\main\bte_main.c
static void bte_hci_enable(void) { APPL_TRACE_DEBUG1("%s", __FUNCTION__); preload_start_wait_timer(); if (bt_hc_if) { int result = bt_hc_if->init(&hc_callbacks, btif_local_bd_addr.address); ... if (hci_logging_enabled == TRUE || hci_logging_config == TRUE) bt_hc_if->logging(BT_HC_LOGGING_ON, hci_logfile); #if (defined (BT_CLEAN_TURN_ON_DISABLED) && BT_CLEAN_TURN_ON_DISABLED == TRUE) APPL_TRACE_DEBUG1("%s Not Turninig Off the BT before Turninig ON", __FUNCTION__); /* Do not power off the chip before powering on if BT_CLEAN_TURN_ON_DISABLED flag is defined and set to TRUE to avoid below mentioned issue. Wingray kernel driver maintains a combined counter to keep track of BT-Wifi state. Invoking set_power(BT_HC_CHIP_PWR_OFF) when the BT is already in OFF state causes this counter to be incorrectly decremented and results in undesired behavior of the chip. This is only a workaround and when the issue is fixed in the kernel this work around should be removed. */ #else /* toggle chip power to ensure we will reset chip in case a previous stack shutdown wasn't completed gracefully */ bt_hc_if->set_power(BT_HC_CHIP_PWR_OFF); #endif bt_hc_if->set_power(BT_HC_CHIP_PWR_ON); bt_hc_if->preload(NULL); } }
找到bt_hc_interface_t
接口在bt_hci_bdroid.c
中set_power()
的具体实现,首先设置了power的状态,然后调用厂商接口bt_vnd_if
中的BT_VND_OP_POWER_CTRL
所对应的函数,执行芯片的上电操作。
代码位置:external\bluetooth\bluedroid\hci\src\bt_hci_bdroid.c
/** Chip power control */ static void set_power(bt_hc_chip_power_state_t state) { int pwr_state; BTHCDBG("set_power %d", state); /* Calling vendor-specific part */ pwr_state = (state == BT_HC_CHIP_PWR_ON) ? BT_VND_PWR_ON : BT_VND_PWR_OFF; if (bt_vnd_if) bt_vnd_if->op(BT_VND_OP_POWER_CTRL, &pwr_state); else ALOGE("vendor lib is missing!"); }
找到bt_hc_interface_t
接口在bt_hci_bdroid.c
中preload()
的具体实现,其就是发送了一个事件,也就是向我们前面在bt_hci_bdroid.c
创建的线程bt_hc_worker_thread
发送了HC_EVENT_PRELOAD
消息,我们跳到线程里对该消息的处理函数中,可以看到,其首先打开了串口userial_open(USERIAL_PORT_1)
,然后调用了vendor定义的BT_VND_OP_FW_CFG
所对应的函数进行芯片framework的config操作。
代码位置:external\bluetooth\bluedroid\hci\src\bt_hci_bdroid.c
/** Called prio to stack initialization */ static void preload(TRANSAC transac) { BTHCDBG("preload"); bthc_signal_event(HC_EVENT_PRELOAD); } ... static void *bt_hc_worker_thread(void *arg) { ... while (lib_running) { pthread_mutex_lock(&hc_cb.mutex); while (ready_events == 0) { pthread_cond_wait(&hc_cb.cond, &hc_cb.mutex); } events = ready_events; ready_events = 0; pthread_mutex_unlock(&hc_cb.mutex); ... if (events & HC_EVENT_PRELOAD) { userial_open(USERIAL_PORT_1); /* Calling vendor-specific part */ if (bt_vnd_if) { bt_vnd_if->op(BT_VND_OP_FW_CFG, NULL); } else { if (bt_hc_cbacks) bt_hc_cbacks->preload_cb(NULL, BT_HC_PRELOAD_FAIL); } } ... } ALOGI("bt_hc_worker_thread exiting"); lib_running = 0; pthread_exit(NULL); return NULL; // compiler friendly }
在userial_open
中主要调用vendor定义的BT_VND_OP_USERIAL_OPEN
所对应的函数进行userial的打开操作,然后再创建了一个串口读取线程userial_read_thread
。
代码位置:external\bluetooth\bluedroid\hci\src\userial.c
uint8_t userial_open(uint8_t port) { ... if (userial_running) { /* Userial is open; close it first */ userial_close(); utils_delay(50); } ... /* Calling vendor-specific part */ if (bt_vnd_if) { result = bt_vnd_if->op(BT_VND_OP_USERIAL_OPEN, &fd_array); ... } else { ALOGE("userial_open: missing vendor lib interface !!!"); ALOGE("userial_open: unable to open UART port"); return FALSE; } ... if (pthread_create(&(userial_cb.read_thread), &thread_attr, \ userial_read_thread, NULL) != 0 ) { ALOGE("pthread_create failed!"); return FALSE; } ... return TRUE; }
到现在已经完成了
bte_hci_enable
的全部操作,回忆下,其首先绑定了蓝牙芯片厂商定制功能函数,首先调用了vendor芯片的init函数;然后根据实际需要,通过宏if语句绑定了hci函数体hci_h4_func_table
,并调用其init函数进行hci的初始化;然后调用了userial和lpm的初始化,并创建了了用于蓝牙hc工作的主线程;接着进行了蓝牙的上电操作;最后进行了蓝牙的preload操作,包括打开userial,创建userial read线程,并执行蓝牙芯片的framework config操作。
再次回到bte_main.c
中的bte_main_enable()
函数,其最后create了一个GKI任务,并启动了该任务。
代码位置:external\bluetooth\bluedroid\main\bte_main.c
void bte_main_enable() { APPL_TRACE_DEBUG1("%s", __FUNCTION__); /* Initialize BTE control block */ BTE_Init(); lpm_enabled = FALSE; bte_hci_enable(); GKI_create_task((TASKPTR)btu_task, BTU_TASK, BTE_BTU_TASK_STR, (UINT16 *) ((UINT8 *)bte_btu_stack + BTE_BTU_STACK_SIZE), sizeof(bte_btu_stack)); GKI_run(0); }
至此,蓝牙的enable操作的就全部结束了,文章中存在很多问题,欢迎大家的指正。
- 【Android4.4蓝牙代码分析】- 蓝牙Enable过程
- 【Android4.4蓝牙代码分析】- 蓝牙Enable过程
- Android4.2蓝牙Enable完全分析
- Android4.2蓝牙Enable完全分析
- Android4.2蓝牙Enable完全分析
- 蓝牙开启流程(enable)分析
- Android4.4 蓝牙源码部分分析
- android4.0 蓝牙启动分析
- 蓝牙协议分析_基本概念及Android4.4 BT代码架构
- Android4.4蓝牙耳机HFP流程分析-1
- Android4.4蓝牙耳机HFP流程分析-2
- Android4.4蓝牙耳机HFP流程分析-3
- Android4.4蓝牙耳机HFP流程分析-3
- Android4.0蓝牙打开流程分析
- Android BlueDroid(三):BlueDroid蓝牙开启过程enable
- Android BlueDroid(三):BlueDroid蓝牙开启过程enable
- Android BlueDroid(三):BlueDroid蓝牙开启过程enable
- Android BlueDroid(三):BlueDroid蓝牙开启过程enable
- 关于UML图
- HDU 1025 Constructing Roads In JGShining's Kingdom(LIS +二分)
- Code Forces 557 C. Arthur and Table(贪心)
- c++ bitset与位压缩
- 深入JVM
- 【Android4.4蓝牙代码分析】- 蓝牙Enable过程
- iOS中集合遍历方法的比较和技巧
- SAP IDES ECC 6.0安装完后,没有数据
- HTTPS隧道
- hdu5311
- 同现矩阵
- CursorAdapter的使用:获取手机联系人
- Android 多分辨率自适应总结
- 诗《风云续》