蓝牙上层协议,服务端的启动,获取以及蓝牙设备的连接

1,蓝牙协议/服务端的启动

上一篇文章中,分析了Bluetooth.apk启动过程,启动Bluetooth.apk时,一般启动了AdapterService这一对应的服务。查看package/app/Bluetooth的源码,里面主要是一些具体的协议,其中每一个协议对应一个具体的服务。那么,这些服务是何时以及如何启动的呢?

在android 5.1 中,打开蓝牙时,在AdapterService的setProfileServiceState中就会逐个启动支持的服务,方法如下:

private void setProfileServiceState(Class[] services, int state) {
        if (state != BluetoothAdapter.STATE_ON && state != BluetoothAdapter.STATE_OFF) {
            debugLog("setProfileServiceState() - Invalid state, leaving...");
            return;
        }

        int expectedCurrentState= BluetoothAdapter.STATE_OFF;
        int pendingState = BluetoothAdapter.STATE_TURNING_ON;
        if (state == BluetoothAdapter.STATE_OFF) {
            expectedCurrentState= BluetoothAdapter.STATE_ON;
            pendingState = BluetoothAdapter.STATE_TURNING_OFF;
        }

        for (int i=0; i 

但是在android 6.0 中,在打开蓝牙,最后调用AdapterService的

setGattProfileServiceState的仅仅启动GattService这一服务,紧接着的调用

BluetoothAdapter的enable方法, notifyUserAction方法最后会调用setProfileServiceState方法启动其他的服务,但是这样做好像意义不大。

public boolean enable() {
        android.util.SeempLog.record(56);
        int state = STATE_OFF;
        if (isEnabled() == true){
            if (DBG) Log.d(TAG, "enable(): BT is already enabled..!");
            return true;
        }
        //Use service interface to get the exact state
        if (mService != null) {
            try {
               state = mService.getState();
            } catch (RemoteException e) {Log.e(TAG, "", e);}
        }

        if (state == BluetoothAdapter.STATE_BLE_ON) { // 蓝牙已经打开
                Log.e(TAG, "BT is in BLE_ON State");
                notifyUserAction(true); // 发出通知
                return true;
        }
        try {
            return mManagerService.enable();
        } catch (RemoteException e) {Log.e(TAG, "", e);}
        return false;
    }

 在android 6.0中,其他协议的服务启动我有些疑惑,到底在什么时候启动的呢?

请看下节。

2,设置里服务端的启动

在手机里面,这些服务应该都有获取,并且服务端和客户端已经绑定,那么代码在哪儿呢?

在这里android 5.1和android 6.0还是有些微小的区别,代码路径不一样,在android6.0 中,设置里面之外,还有一个文件夹,路径如下,

frameworks\base\packages\SettingsLib\src\com\android\settingslib\bluetooth

包含的文件:

蓝牙上层协议,服务端的启动,获取以及蓝牙设备的连接_第1张图片

基本上每一个profile文件就对应;而在android 5.1 中,这些文件都包含在

packages\apps\Settings\src\com\android\settings\bluetooth之中。其他的基本原理是完全一样的。

启动设置,打开蓝牙设置,设置里的协议客户端就会创建,然后启动服务端并且和服务端绑定在一起,流程图如下:

蓝牙上层协议,服务端的启动,获取以及蓝牙设备的连接_第2张图片

这里以PanProfile为例来说明, PanProfile的构造函数如下,

PanProfile(Context context) {
        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
        adapter.getProfileProxy(context, new PanServiceListener(),
                BluetoothProfile.PAN);
    }


 private BluetoothPan mService;
 private boolean mIsProfileReady;

private final class PanServiceListener
            implements BluetoothProfile.ServiceListener {

        public void onServiceConnected(int profile, BluetoothProfile proxy) {
            if (V) Log.d(TAG,"Bluetooth service connected");
            mService = (BluetoothPan) proxy;
            mIsProfileReady=true;
        }

        public void onServiceDisconnected(int profile) {
            if (V) Log.d(TAG,"Bluetooth service disconnected");
            mIsProfileReady=false;
        }
    }

getProfileProxy方法下节再论述。

3,蓝牙协议/客户端的获取

在蓝牙开发中,服务端的各种协议已经封装好了,如果是我们自己开发,我们怎么样才能调用呢?对应的客户端是啥呢?开发时,比如现在想进行蓝牙通话,获取蓝牙通话的客户端对象。

蓝牙上层协议,服务端的启动,获取以及蓝牙设备的连接_第3张图片

private final BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
	private BluetoothHeadsetClient mHfpClient = null;

一般在组件的oncreate方法中调用enableHFP方法来获取蓝牙通话的客户端对象,代码如下:

private void enableHFP() {
	mBluetoothAdapter.getProfileProxy(getApplicationContext(), new ServiceListener() {
			public void onServiceConnected(int profile,BluetoothProfile proxy) {
				if (profile == BluetoothProfile.HEADSET_CLIENT) {
					android.util.Log.d("fang ", "init mBluetoothHeadset");
					mHfpClient = (BluetoothHeadsetClient) proxy;
				}
			}
			public void onServiceDisconnected(int profile) {
				if (profile == BluetoothProfile.HEADSET_CLIENT) {
					mHfpClient = null;
				}
			}
		}, BluetoothProfile.HEADSET_CLIENT);
	}

首先看看getProfileProxy方法

public boolean getProfileProxy(Context context, BluetoothProfile.ServiceListener listener,
                                   int profile) {
        if (context == null || listener == null) return false;

        if (profile == BluetoothProfile.HEADSET) {
            BluetoothHeadset headset = new BluetoothHeadset(context, listener);
            return true;
        } else if (profile == BluetoothProfile.A2DP) {
            BluetoothA2dp a2dp = new BluetoothA2dp(context, listener);
            return true;
        } else if (profile == BluetoothProfile.A2DP_SINK) {
            BluetoothA2dpSink a2dpSink = new BluetoothA2dpSink(context, listener);
            return true;
        } else if (profile == BluetoothProfile.AVRCP_CONTROLLER) {
            BluetoothAvrcpController avrcp = new BluetoothAvrcpController(context, listener);
            return true;
        } else if (profile == BluetoothProfile.INPUT_DEVICE) {
            BluetoothInputDevice iDev = new BluetoothInputDevice(context, listener);
            return true;
        } else if (profile == BluetoothProfile.PAN) {
            BluetoothPan pan = new BluetoothPan(context, listener);
            return true;
        } else if (profile == BluetoothProfile.DUN) {
            BluetoothDun dun = new BluetoothDun(context, listener);
            return true;
        } else if (profile == BluetoothProfile.HEALTH) {
            BluetoothHealth health = new BluetoothHealth(context, listener);
            return true;
        } else if (profile == BluetoothProfile.MAP) {
            BluetoothMap map = new BluetoothMap(context, listener);
            return true;
        } else if (profile == BluetoothProfile.HEADSET_CLIENT) {
            BluetoothHeadsetClient headsetClient = new BluetoothHeadsetClient(context, listener);
            return true;
        } else if (profile == BluetoothProfile.SAP) {
            BluetoothSap sap = new BluetoothSap(context, listener);
            return true;
        } else if (profile == BluetoothProfile.HID_DEVICE) {
            BluetoothHidDevice hidd = new BluetoothHidDevice(context, listener);
            return true;
        } else {
            return false;
        }
}

这一共有12个服务,对应12个协议。这些客户端的类都是继承自

BluetoothProfile 典型的工厂模式,得到不同的实例对象。以

BluetoothHeadsetClient协议为例,论述如下流程,

BluetoothHeadsetClient的构造函数如下:

BluetoothHeadsetClient(Context context, ServiceListener l) {
        mContext = context;
        mServiceListener = l;
        mAdapter = BluetoothAdapter.getDefaultAdapter();

        IBluetoothManager mgr = mAdapter.getBluetoothManager();
        if (mgr != null) {
            try {
                mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
            } catch (RemoteException e) {
                Log.e(TAG,"",e);
            }
        }

        doBind();
    }
boolean doBind() {
        Intent intent = new Intent(IBluetoothHeadsetClient.class.getName());
       ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
        intent.setComponent(comp);
        if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
                 android.os.Process.myUserHandle())) {
            Log.e(TAG, "Could not bind to Bluetooth Headset Client Service with " + intent);
            return false;
        }
        return true;
    }

AndroidManifest.xml中的HeadsetClientService定义如下,


            
                
            
        

bindServiceAsUser挂进程绑定在此就不论述了,直接看mConnection对象的方法,

private ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName className, IBinder service) {
            if (DBG) Log.d(TAG, "Proxy object connected");
            mService = IBluetoothHeadsetClient.Stub.asInterface(service);

            if (mServiceListener != null) {
                mServiceListener.onServiceConnected(BluetoothProfile.HEADSET_CLIENT,
                        BluetoothHeadsetClient.this);
            }
        }
        @Override
        public void onServiceDisconnected(ComponentName className) {
            if (DBG) Log.d(TAG, "Proxy object disconnected");
            mService = null;
            if (mServiceListener != null) {
                mServiceListener.onServiceDisconnected(BluetoothProfile.HEADSET_CLIENT);
            }
        }
};

所以,最后的结果是将运行于第三方apk的BluetoothHeadsetClient对象和运行于Bluetooth.apk的HeadsetClientService对应起来了。

mServiceListener就是enableHFP方法中的匿名ServiceListener类的对象。看到此,恍然大悟了, getProfileProxy方法根据第三个参数首先创建对应的客户端类,然后将客户端和Bluetooth.apk的服务端进行连接,最后返回客户端,这是典型的C/S模式。这样,12个客户端和服务端协议一一对应了,但是上层蓝牙不止这12个协议。好了,现在每个协议的客户端可以获取了,万事俱备了,接下来看看每个协议的使用场景和功能吧。

4,蓝牙设备的连接

最开始的时候,每个协议的客户端都有一个connect方法,但是我一直都不知道是什么时候调用的,设备到底是如何连接的。过了很久很久之后才发现,还是在设置里,点击已配对的设备就可以进行连接,最后是每个协议独立的连接。这是基于android6.0,但是5.1的几乎完全一样,还是以BluetoothPan为例说明连接的部分流程,流程图如下

蓝牙上层协议,服务端的启动,获取以及蓝牙设备的连接_第4张图片

步骤其实很简单,就是从协议的客户端跨进程调用到对应的服务端,然后通过JNI机制调用C/C++最后来完成连接。只有设备的协议连接起来了,才可以进行进一步的操作。






 
  





你可能感兴趣的:(---【蓝牙框架分析】)