这篇文章将所有的android蓝牙的东西都集合在这里,主要分一下几个部分,所有分析都基于Bluedroid:
(1) Android Bluedroid蓝牙基本框架
(2) 主要目录及文件结构
(3) 蓝牙主要的支持的profile
(4) 蓝牙基本流程分析:蓝牙启动, 蓝牙搜索, 蓝牙连接, 蓝牙传输文件,蓝牙通话和播放音乐
(1) Android Bluedroid蓝牙基本框架
根据上图,代码调用过程一般基于下面的流程
APP->Framework---->(通过Binder)BluetoothService-->(通过JNI)调用Native Bluetooth->bluedroid->hci
(2) 模块的主要目录以及文件结构:
APP:
Settings
packages/apps/Settings/src/com/android/settings/bluetooth
主要文件说明:
BluetoothEnabler.java 界面上蓝牙开启、关闭的开关就是它了,
BluetoothSettings.java 主界面,用于管理配对和连接设备
LocalBluetoothManager.java 提供了蓝牙API上的简单调用接口,这里只是开始。
CachedBluetoothDevice.java 描述蓝牙设备的类,对BluetoothDevice的再封装
BluetoothPairingDialog.java 那个配对提示的对话框
Phone
packages/apps/services/Telecom/src/com/android/server/telecom/BluetoothManager.java
这里是通话调用蓝牙Audio,
connectBluetoothAudio
disconnectBluetoothAudio
Framework:
/frameworks/base/core/java/android/bluetooth/
BluetoothA2dp.java A2DP的功能实现
BluetoothAdapter.java 蓝牙action的定义,虚拟设备属性以及操作方法
BluetoothAudioGateway.java 蓝牙语音网关
BluetoothClass.java 蓝牙设备类型的定义
BluetoothDevice.java 蓝牙设备属性
BluetoothDevicePicker.java 定义远程蓝牙设备的特性,比如需要认证,设备类型
BluetoothHeadset.java 定义蓝牙headset功能的属性以及接口
BluetoothInputStream.java 蓝牙流接口的实现(输入流)
BluetoothOutputStream.java 蓝牙流接口的实现(输出流)
BluetoothServerSocket.java 蓝牙socket服务端具备的方法
BluetoothSocket.java 蓝牙socket的封装
BluetoothUuid.java 蓝牙uuid的定义以及uuid的解析
(3) 蓝牙主要的支持的profile
HFP/HSP
A2DP
AVRCP
PBAP
DUN
OPP
PAN
(4) 蓝牙基本流程分析:
a. 蓝牙开启:
首先是BluetoothManagerService的启动, 这个服务也是在SystemServer中启动的, 在开机后,SystemServer进程由zygote进程fork出来后,会启动一系列的service,这里面就有BluetoothManagerService:
frameworks/base/services/java/com/android/server/SystemServer.java
private void startOtherServices() {
BluetoothManagerService bluetooth = null;
//初始化一个BluetoothManagerService;
bluetooth = new BluetoothManagerService(context);
ServiceManager.addService(BluetoothAdapter.BLUETOOTH_MANAGER_SERVICE, bluetooth);
}
看一下BluetoothManagerService的构造函数
BluetoothManagerService(Context context) {
loadStoredNameAndAddress(); //读取蓝牙打开默认名称和地址
if (isBluetoothPersistedStateOn()) { //判断蓝牙是否打开
mEnableExternal = true; //如果蓝牙打开,这个设为true,等boot完后,开启enable 蓝牙的过程
}
}
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
else if (Intent.ACTION_BOOT_COMPLETED.equals(action)) {
synchronized(mReceiver) {
if (mEnableExternal && isBluetoothPersistedStateOnBluetooth()) {
//Enable
if (DBG) Log.d(TAG, "Auto-enabling Bluetooth.");
sendEnableMsg(mQuietEnableExternal);
}
}
}
广播中接收Boot是否完成, 完成后调用sendEnable来开启蓝牙,mEnableExternal这个值就在这里用到了。
b. 点击蓝牙开关开启蓝牙流程
Settings菜单点击菜单开启蓝牙:
APP层路径packages/apps/Settings/src/com/android/settings/bluetooth
BluetoothSettings.java
public void onActivityCreated(Bundle savedInstanceState) {
mSwitchBar = activity.getSwitchBar(); //界面上的swtichbar控件
mBluetoothEnabler = new BluetoothEnabler(activity, mSwitchBar); //传送给BluetoothEnabler, 通过BluetoothEnable控制
mBluetoothEnabler.setupSwitchBar();
}
BluetoothEnabler.java
private final LocalBluetoothAdapter mLocalAdapter; //localBluetoothAdapter
public BlutoothEnable(){ //构造函数,定义了localBluetoothManager和LocalBluetoothAdapter
LocalBluetoothManager manager = LocalBluetoothManager.getInstance(context);
mLocalAdapter = manager.getBluetoothAdapter();
}
public void resume(Context context) {
// Bluetooth state is not sticky, so set it manually
handleStateChanged(mLocalAdapter.getBluetoothState()); //设置初始状态
mSwitchBar.addOnSwitchChangeListener(this); //设置switch监听
}
public void onSwitchChanged(Switch switchView, boolean isChecked) {
if (mLocalAdapter != null) {
mLocalAdapter.setBluetoothEnabled(isChecked); //
}
}
LocalBluetoothAdapter.java
public void setBluetoothEnabled(boolean enabled) {
private final BluetoothAdapter mAdapter;
boolean success = enabled? mAdapter.enable(): mAdapter.disable(); 调用BluetoothAdapter的enable/disable
}
通过调用BluetoothAdapter的函数,就调用到了framework的接口:
LocalBluetoothAdapter.java
private final IBluetoothManager mManagerService;
public static synchronized BluetoothAdapter getDefaultAdapter() {
IBluetoothManager managerService = IBluetoothManager.Stub.asInterface(b); //这边会返回一个managerService的代理
}
public boolean enable() {
return mManagerService.enable(ActivityThread.currentPackageName()); //通过代理调用BluetoothManagerService的enable.
}
BluetoothManagerService
class BluetoothManagerService extends IBluetoothManager.Stub{
private final BluetoothHandler mHandler;
private IBluetooth mBluetooth;
public boolean enable(String callingPackage) {
//这里会获取蓝牙的权限
synchronized(mReceiver) {
//通过发送消息的方式enable
sendEnableMsg(false);
}
}
private void sendEnableMsg(boolean quietMode) {
//这边回去发送消息, quietMode决定打开后是否需要AutoConnect,这边是false
mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_ENABLE,
quietMode ? 1 : 0, 0));
}
//Handler是BluetoothManagerService的内部类,这边处理接收的命令
private class BluetoothHandler extends Handler {
public void handleMessage(Message msg) {
case MESSAGE_ENABLE:
//调用handleEnable函数处理
handleEnable(msg.arg1 == 1);
break;
case MESSAGE_BLUETOOTH_SERVICE_CONNECTED:
mBluetooth = IBluetooth.Stub.asInterface(service);
break;
}
}
private void handleEnable(boolean quietMode) {
synchronized(mConnection) {
try {
//传进来是false,所以走enable,即开启会重新连接
if (!mQuietEnable) {
//调用mBluetooth的enable,mBluetooth上面有定义,是IBluetooth的代理, server端在package/apps/Bluetooth里面
if(!mBluetooth.enable()) {
}
}
else {
if(!mBluetooth.enableNoAutoConnect()) {
}
}
} catch (RemoteException e) {
Log.e(TAG,"Unable to call enable()",e);
}
}
}
}
之前调用IBluetooth的service端的部分:
AdapterService.java
static { //这里添加了so库,并定义了一些 native函数
System.load("/system/lib/libbluetooth_jni.so");
classInitNative();
}
private static class AdapterServiceBinder extends IBluetooth.Stub {
public boolean enable() {
return service.enable(); //这边又要看这个service,这个service即是 AdapterService
}
}
boolean enable() {
return enable (false);
}
public synchronized boolean enable(boolean quietMode) {
//这边会发送一个消息到状态机AdapaterState
Message m =
mAdapterStateMachine.obtainMessage(AdapterState.USER_TURN_ON);
mAdapterStateMachine.sendMessage(m);
}
void processStart() {
//启动蓝牙的部分, 如果是第一次开启的话, 走下面的路径, 继续想state状态机发送AdapterState.STARTED状态
if (!mProfilesStarted && supportedProfileServices.length >0) {
//Startup all profile services
setProfileServiceState(supportedProfileServices,BluetoothAdapter.STATE_ON);
}else {
debugLog("processStart() - Profile Services alreay started");
mAdapterStateMachine.sendMessage(mAdapterStateMachine.obtainMessage(AdapterState.STARTED));
}
}
AdapterState.java 状态机文件,负责跟AdapterService的沟通
private class OffState extends State {
public boolean processMessage(Message msg) {
switch(msg.what) {
case USER_TURN_ON:
adapterService.processStart(); //adpaterService调用processStart函数
break;
}
}
最后,看一下状态机里面的函数
private class PendingCommandState extends State {
public boolean processMessage(Message msg) {
boolean ret = adapterService.enableNative(); //这边就调用到jni的地方了
}
看一下简单的流程图, 大体一致,但也稍微有不同的地方
这边只到了JNI,下面JNI如何调用CPP的呢~
这边调用packages/apps/Bluetooth/jni下面的jni文件:
com_android_bluetooth_btservice_AdapterService.cpp
static jboolean enableNative(JNIENv* env, jobject obj){
int ret = sBluetoothInterface->enable();
}
在然后好像真的没有了, 后面进入到hal,调用Bluedroid协议栈了
hardware/libhardware/include/hardware/bluetooth.h
typedef struct{
int(*enable)(void);
}bt_interface_t;
Bluedroid协议栈位于external/bluetooth/bluedroid
bluetooth.c
static int enable(void){
return btif_enable_bluetooth();
}
btif_core.c
bt_status_t btif_enable_bluetooth(void)
{
bte_main_enable();
}
bte_main.c
void bte_main_enable(){
BTE_Init();
GKI_create_task(); //创建GKI task
bte_hci_enable();
GKI_run();
}
c. 蓝牙搜索:
APP测:
BluetoothSettings.java
//蓝牙状态改变监听
public void onBluetoothStateChanged(int bluetoothState) {
super.onBluetoothStateChanged(bluetoothState);
updateContent(bluetoothState);
}
private void updateContent(int bluetoothState) {
case BluetoothAdapter.STATE_ON: //蓝牙开启完成后,开始扫描
if (!mInitialScanStarted) {
startScanning();
}
break;
case BluetoothAdapter.STATE_TURNING_ON: //蓝牙开启中,将scanStart设置为false
mInitialScanStarted = false;
break;
}
这边的BluetoothAdapter.STATE有4个状态:
STATE_OF = 10;
STATE_TURNING_ON = 11;
STATE_ON = 12;
STATE_TURNING_OFF = 13;
private void startScanning() {
mLocalAdapter.startScanning(true);//调用localAdapter的startScanning函数
}
LocalBluetoothAdapter.java
void startScanning(boolean force) {
// If we are playing music, don't scan unless forced.
//这里回去判断a2dp profile,如果正在a2dp存在,则不能扫描
A2dpProfile a2dp = mProfileManager.getA2dpProfile();
if (a2dp != null && a2dp.isA2dpPlaying()) {
return;
}
A2dpSinkProfile a2dpSink = mProfileManager.getA2dpSinkProfile();
if ((a2dpSink != null) && (a2dpSink.isA2dpPlaying())){
return;
}
if (mAdapter.startDiscovery()) { //调用framwork的接口
mLastScan = System.currentTimeMillis();
}
}
Framework:
BluetoothAdapter.java
private IBluetooth mService; //这么快就用到IBluetooth了。。。
BluetoothAdapter(IBluetoothManager managerService) {
try {
//构造函数里直接就获取mService,这个mService跟managerService是一样一样的,是IBluetooth的客户端代理,跟Service(AdapterService)通讯
mService = managerService.registerAdapter(mManagerCallback);
} catch (RemoteException e) {Log.e(TAG, "", e);}
}
public boolean startDiscovery() {
if (mService != null) return mService.startDiscovery(); //开始扫描
}
还是来看一下mService是如何获取的
BluetoothManagerService.java
public IBluetooth registerAdapter(IBluetoothManagerCallback callback){
synchronized(mConnection) {
return mBluetooth; //就是返回BluetoothManagerService的mBluetooth
}
}
Service (Service的目录在packages/apps/bluetooth里面)
AdapterService.java
private static class AdapterServiceBinder extends IBluetooth.Stub {
public boolean startDiscovery() {
AdapterService service = getService();
return service.startDiscovery();
}
}
这里有个内部类AdapterServiceBinder,是远程通讯的服务端:
直接调用了AdapterService的startDiscovery函数
boolean startDiscovery() {
enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
"Need BLUETOOTH ADMIN permission");
//do not allow new connections with active multicast
A2dpService a2dpService = A2dpService.getA2dpService();
if (a2dpService != null &&
a2dpService.isMulticastOngoing(null)) {
Log.i(TAG,"A2dp Multicast is Ongoing, ignore discovery");
return false;
}
return startDiscoveryNative();
}
这边也是简单粗暴的,直接返回startDiscoveryNative(),调用JNI函数
JNI
JNI的文件需要到packages/apps/bluetooth/jni下面,adapterservice对应的jni文件为
com_android_bluetooth_btservice_AdapterService.cpp
static jboolean startDiscoveryNative(JNIEnv* env, jobject obj) {
int ret = sBluetoothInterface->start_discovery();
}
HAL
hal主要看hanrdware/libhardware/include/hardware/bluetooth.h
int (*start_discovery)(void);
//Bluedroid协议栈部分
bluetooth.c
static int statrt_discovery(void){
retun btif_dm_start_discovery();
}
btif_dm.c
这个函数start device discovery/inquiry
bt_status_t btif_dm_start_discovery(void){
/*find nearby devices*/
BTA_DmSearch(...);
}
d. 蓝牙扫描结果返回
扫描结果反馈到上层则是从协议栈->hal->bluetoothService->APP
external/bluetooth/bluedroid/btif/src/
btif_dm.c
static void btif_dm_search_devices_evt (UINT16 event, char *p_param)
{
case BTA_DM_INQ_RES_EVT:
/* Callback to notify upper layer of device */
//调用注册的callback, device_found_cb
HAL_CBACK(bt_hal_cbacks, device_found_cb,num_properties, properties);
break;
}
HAL
bluetooth.h
//
typedef void (*device_found_callback)(int num_properties,
bt_property_t *properties);
JNI
com_android_bluetooth_btservice_AdapterService.cpp
static void device_found_callback(int num_properties, bt_property_t *properties) {
if (sJniCallbacksObj) {
callbackEnv->CallVoidMethod(sJniCallbacksObj, method_deviceFoundCallback, addr);
}
}
Service
//deviceFoundCallback
RemoteDevices.java
void deviceFoundCallback(byte[] address) {
Intent intent = new Intent(BluetoothDevice.ACTION_FOUND); //send broadcast
intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
intent.putExtra(BluetoothDevice.EXTRA_CLASS,
new BluetoothClass(Integer.valueOf(deviceProp.mBluetoothClass)));
intent.putExtra(BluetoothDevice.EXTRA_RSSI, deviceProp.mRssi);
intent.putExtra(BluetoothDevice.EXTRA_NAME, deviceProp.mName);
mAdapterService.sendBroadcast(intent, mAdapterService.BLUETOOTH_PERM);
}
这里调用发送广播,Action_Found给到上层
APP(Settings)
BluetoothEventManager.java
BluetoothEventManager(LocalBluetoothAdapter adapter,
CachedBluetoothDeviceManager deviceManager, Context context) {
mLocalAdapter = adapter;
mDeviceManager = deviceManager;
mAdapterIntentFilter = new IntentFilter();
mProfileIntentFilter = new IntentFilter();
mHandlerMap = new HashMap<String, Handler>();
mContext = context;
// Bluetooth on/off broadcasts
addHandler(BluetoothAdapter.ACTION_STATE_CHANGED, new AdapterStateChangedHandler());
// Discovery broadcasts
addHandler(BluetoothAdapter.ACTION_DISCOVERY_STARTED, new ScanningStateChangedHandler(true));
addHandler(BluetoothAdapter.ACTION_DISCOVERY_FINISHED, new ScanningStateChangedHandler(false));
addHandler(BluetoothDevice.ACTION_FOUND, new DeviceFoundHandler());
addHandler(BluetoothDevice.ACTION_DISAPPEARED, new DeviceDisappearedHandler());
addHandler(BluetoothDevice.ACTION_NAME_CHANGED, new NameChangedHandler());
// Pairing broadcasts
addHandler(BluetoothDevice.ACTION_BOND_STATE_CHANGED, new BondStateChangedHandler());
addHandler(BluetoothDevice.ACTION_PAIRING_CANCEL, new PairingCancelHandler());
// Fine-grained state broadcasts
addHandler(BluetoothDevice.ACTION_CLASS_CHANGED, new ClassChangedHandler());
addHandler(BluetoothDevice.ACTION_UUID, new UuidChangedHandler());
// Dock event broadcasts
addHandler(Intent.ACTION_DOCK_EVENT, new DockEventHandler());
mContext.registerReceiver(mBroadcastReceiver, mAdapterIntentFilter);
setDefaultBtName();
}
这边注册广播接收器
addHandler(BluetoothDevice.ACTION_FOUND, new DeviceFoundHandler());
private class DeviceFoundHandler implements Handler {
public void onReceive(Context context, Intent intent,
BluetoothDevice device) {
if (cachedDevice == null) {
cachedDevice = mDeviceManager.addDevice(mLocalAdapter, mProfileManager, device);
Log.d(TAG, "DeviceFoundHandler created new CachedBluetoothDevice: "
+ cachedDevice);
// callback to UI to create Preference for new device
dispatchDeviceAdded(cachedDevice);
}
}
}
DeviceFoundHandler接收广播,并调用dispatchDeviceAdded(cachedDevice);刷新上层显示
private void dispatchDeviceAdded(CachedBluetoothDevice cachedDevice) {
synchronized (mCallbacks) {
for (BluetoothCallback callback : mCallbacks) {
callback.onDeviceAdded(cachedDevice);
}
}
}
调用callback.onDeviceAdded(cachedDevice); 回调返给上层
ListFragment DeviceListPreferenceFragment.java
public void onDeviceAdded(CachedBluetoothDevice cachedDevice) {
、、、
}
DeviceListPreferenceFragment继承BluetoothCallback接口,重写onDeviceAdded.
蓝牙连接:
蓝牙OPP文件传输:
起点自函数packages/apps/Bluetooth/src/com/android/bluetooth/opp/BluetoothOppLauncherActivity.java
if (action.equals(Intent.ACTION_SEND) || action.equals(Intent.ACTION_SEND_MULTIPLE)) {
if (!isBluetoothAllowed()) {
Intent in = new Intent(this, BluetoothOppBtErrorActivity.class);
in.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
in.putExtra("title", this.getString(R.string.airplane_error_title));
in.putExtra("content", this.getString(R.string.airplane_error_msg));
startActivity(in);
finish();
return;
}
if (action.equals(Intent.ACTION_SEND)) {
Thread t = new Thread(new Runnable() {
public void run() {
BluetoothOppManager.getInstance(BluetoothOppLauncherActivity.this)
.saveSendingFileInfo(type,stream.toString(), false);
//Done getting file info..Launch device picker and finish this activity
launchDevicePicker();
finish();
}
});
t.start();
return;
}
}
isBluetoothAllowed()判断Bluetooth是否允许,如果不允许,弹出Error.
如果返回true,则开启个线程,
launchDevicePicker 加载蓝牙列表
private final void launchDevicePicker() {
if (!BluetoothOppManager.getInstance(this).isEnabled()) {
if (V) Log.v(TAG, "Prepare Enable BT!! ");
Intent in = new Intent(this, BluetoothOppBtEnableActivity.class);
in.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(in);
} else {
if (V) Log.v(TAG, "BT already enabled!! ");
Intent in1 = new Intent(BluetoothDevicePicker.ACTION_LAUNCH);
in1.setFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
in1.putExtra(BluetoothDevicePicker.EXTRA_NEED_AUTH, false);
in1.putExtra(BluetoothDevicePicker.EXTRA_FILTER_TYPE,
BluetoothDevicePicker.FILTER_TYPE_TRANSFER);
in1.putExtra(BluetoothDevicePicker.EXTRA_LAUNCH_PACKAGE,
Constants.THIS_PACKAGE_NAME);
in1.putExtra(BluetoothDevicePicker.EXTRA_LAUNCH_CLASS,
BluetoothOppReceiver.class.getName());
if (V) {Log.d(TAG,"Launching " +BluetoothDevicePicker.ACTION_LAUNCH );}
startActivity(in1);
}
}
BluetoothOppManager.getInstance(this).isEnabled()判断蓝牙是否打开,如果打开,则跳转到列表
DevicePickerFragment.java
@Override
void onDevicePreferenceClick(BluetoothDevicePreference btPreference) {
mLocalAdapter.stopScanning();
LocalBluetoothPreferences.persistSelectedDeviceInPicker(
getActivity(), mSelectedDevice.getAddress());
if ((btPreference.getCachedDevice().getBondState() ==
BluetoothDevice.BOND_BONDED) || !mNeedAuth) {
sendDevicePickedIntent(mSelectedDevice);
finish();
} else {
super.onDevicePreferenceClick(btPreference);
}
}
private void sendDevicePickedIntent(BluetoothDevice device) {
mDeviceSelected = true;
Intent intent = new Intent(BluetoothDevicePicker.ACTION_DEVICE_SELECTED);
intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
if (mLaunchPackage != null && mLaunchClass != null) {
intent.setClassName(mLaunchPackage, mLaunchClass);
}
getActivity().sendBroadcast(intent);
}
这边发送一个selectd的广播,搜关键字查询广播接收。
BluetoothOppReceiver.java
public void onReceive(Context context, Intent intent) {
else if (action.equals(BluetoothDevicePicker.ACTION_DEVICE_SELECTED)) {
// Insert transfer session record to database
mOppManager.startTransfer(remoteDevice);
}
}
public void startTransfer(BluetoothDevice device) {
if (V) Log.v(TAG, "Active InsertShareThread number is : " + mInsertShareThreadNum);
InsertShareInfoThread insertThread;
insertThread = new InsertShareInfoThread(device, mMultipleFlag, mMimeTypeOfSendingFile,
mUriOfSendingFile, mNameOfSendingFile, mMimeTypeOfSendingFiles, mUrisOfSendingFiles,
mIsHandoverInitiated);
}
insertThread.start();
}
private class InsertShareInfoThread extends Thread {
public void run() {
insertSingleShare();
}
}
上面步骤即是接收广播后的操作~最终调用insertSingleShare来操作,后面的步骤略掉。
蓝牙接电话与听音乐: