Android4.4(MT8685)源码蓝牙解析--配对
来源:互联网 发布:智慧城市大数据 编辑:程序博客网 时间:2024/04/29 12:15
在Settings的Bluetooth界面中,当用户点击当前的可连接设备时,系统会先对点击的设备进行配对,在BluetoothSettings.java类中对应的源码为:
@Override void onDevicePreferenceClick(BluetoothDevicePreference btPreference) { mLocalAdapter.stopScanning(); super.onDevicePreferenceClick(btPreference); }
这是一个继承至父类的方法,这里首先会让系统停止搜索蓝牙设备,因为当在配对的过程中,同时搜索的话会出现"“Couldn’t pair with **device because of an incorrect PIN or passkey"的错误。接下来会调用父类的onDevicePreferenceClick方法,
void onDevicePreferenceClick(BluetoothDevicePreference btPreference) { btPreference.onClicked(); }
这里会进入BluetoothDevicePreference的onClicked方法,
void onClicked() { int bondState = mCachedDevice.getBondState(); if (mCachedDevice.isConnected()) { askDisconnect(); } else if (bondState == BluetoothDevice.BOND_BONDED) { Xlog.d(TAG, mCachedDevice.getName() + " connect"); mCachedDevice.connect(true); } else if (bondState == BluetoothDevice.BOND_NONE) { pair(); } }这里首先会获取当前蓝牙设备的状态,如果是已经连接的话,就断开连接;如果是已配对的话,就进行连接;如果是未配对的话,就进行配对,这里我们进入到pair方法:
private void pair() { if (!mCachedDevice.startPairing()) { Utils.showError(getContext(), mCachedDevice.getName(), R.string.bluetooth_pairing_error_message); } }
这里通过CachedBluetoothDevice对象mCachedDevice调用startPairing方法,进去看看:
boolean startPairing() { // Pairing is unreliable while scanning, so cancel discovery if (mLocalAdapter.isDiscovering()) { mLocalAdapter.cancelDiscovery(); } if (!mDevice.createBond()) { return false; } mConnectAfterPairing = true; // auto-connect after pairing return true; }
这里首先就会再一次判断当前系统是否是在搜索设备,如果是就取消搜索,接着就是调用BluetoothDevice对象mDevice的createBond方法:
public boolean createBond() { if (sService == null) { Log.e(TAG, "BT not enabled. Cannot create bond to Remote Device"); return false; } try { if (DBG) Log.d(TAG, "createBond: " + this); return sService.createBond(this); } catch (RemoteException e) {Log.e(TAG, "", e);} return false; }
这里和搜索里一样,通过mService来调用createBond方法,这里的mService其实就是AdapterService内部类AdapterServiceBinder的对象,
public boolean createBond(BluetoothDevice device) { if (!Utils.checkCaller()) {Log.e("dy","Utils.checkCaller()==false"); Log.w(TAG,"createBond(): not allowed for non-active user"); return false; } AdapterService service = getService(); if (service == null) return false; return service.createBond(device); }
这里调用AdapterService类的createBond方法
boolean createBond(BluetoothDevice device) { enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); if (deviceProp != null && deviceProp.getBondState() != BluetoothDevice.BOND_NONE) { return false; } // Pairing is unreliable while scanning, so cancel discovery // Note, remove this when native stack improves cancelDiscoveryNative(); Message msg = mBondStateMachine.obtainMessage(BondStateMachine.CREATE_BOND); msg.obj = device; mBondStateMachine.sendMessage(msg); return true; }
这里又会通过cancelDiscoveryNative这个本地方法来取消搜索,接着利用BondStateMachine 的 mBondStateMachine对象发送了一个配对的消息,消息是在BondStateMachine 中接收:
@Override public boolean processMessage(Message msg) { BluetoothDevice dev = (BluetoothDevice)msg.obj; boolean result = false; if (mDevices.contains(dev) && msg.what != CANCEL_BOND && msg.what != BONDING_STATE_CHANGE) { deferMessage(msg); return true; } switch (msg.what) { case CREATE_BOND: result = createBond(dev, false); break; case REMOVE_BOND: result = removeBond(dev, false); break; case CANCEL_BOND: result = cancelBond(dev); break; case BONDING_STATE_CHANGE: int newState = msg.arg1; int reason = getUnbondReasonFromHALCode(msg.arg2); sendIntent(dev, newState, reason); if(newState != BluetoothDevice.BOND_BONDING ) { /* this is either none/bonded, remove and transition */ result = !mDevices.remove(dev); if (mDevices.isEmpty()) { // Whenever mDevices is empty, then we need to // set result=false. Else, we will end up adding // the device to the list again. This prevents us // from pairing with a device that we just unpaired result = false; transitionTo(mStableState); } if (newState == BluetoothDevice.BOND_NONE) { // Set the profile Priorities to undefined clearProfilePriorty(dev); } else if (newState == BluetoothDevice.BOND_BONDED) { // Restore the profile priorty settings setProfilePriorty(dev); } } else if(!mDevices.contains(dev)) result=true; break; default: Log.e(TAG, "Received unhandled event:" + msg.what); return false; } if (result) mDevices.add(dev); return true; } }
当接收到的消息为CREATE_BOND时,执行createBond方法:
private boolean createBond(BluetoothDevice dev, boolean transition) { if (dev.getBondState() == BluetoothDevice.BOND_NONE) { infoLog("Bond address is:" + dev); byte[] addr = Utils.getBytesFromAddress(dev.getAddress()); if (!mAdapterService.createBondNative(addr)) { sendIntent(dev, BluetoothDevice.BOND_NONE, BluetoothDevice.UNBOND_REASON_REMOVED); return false; } else if (transition) { transitionTo(mPendingCommandState); } return true; } return false; }这个方法有返回到AdapterService方法中调用它的createBondNative本地方法(之前在AdapterService中为什么不直接调用createBondNative呢?),接着我们在com_android_bluetooth_btservice_AdapterService中找到对应的jni方法:
static jboolean createBondNative(JNIEnv* env, jobject obj, jbyteArray address) { ALOGV("%s:",__FUNCTION__); jbyte *addr; jboolean result = JNI_FALSE; if (!sBluetoothInterface) return result; addr = env->GetByteArrayElements(address, NULL); if (addr == NULL) { jniThrowIOException(env, EINVAL); return result; } int ret = sBluetoothInterface->create_bond((bt_bdaddr_t *)addr); env->ReleaseByteArrayElements(address, addr, 0); result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; return result;}
这里通过sBluetoothInterface来调用MTK蓝牙相关库的create_bond方法来实现配对,配对完毕后,会想上层回调配对的结果,
static void bond_state_changed_callback(bt_status_t status, bt_bdaddr_t *bd_addr, bt_bond_state_t state) { jbyteArray addr; int i; if (!checkCallbackThread()) { ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__); return; } if (!bd_addr) { ALOGE("Address is null in %s", __FUNCTION__); return; } addr = callbackEnv->NewByteArray(sizeof(bt_bdaddr_t)); if (addr == NULL) { ALOGE("Address allocation failed in %s", __FUNCTION__); return; } callbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *)bd_addr); callbackEnv->CallVoidMethod(sJniCallbacksObj, method_bondStateChangeCallback, (jint) status, addr, (jint)state); checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__); callbackEnv->DeleteLocalRef(addr);}
这里会回调JniCallbacks的bondStateChangeCallback:
void bondStateChangeCallback(int status, byte[] address, int newState) { mBondStateMachine.bondStateChangeCallback(status, address, newState); }
这里又要进入到BondStateMachine的bondStateChangeCallback方法中:
void bondStateChangeCallback(int status, byte[] address, int newState) { BluetoothDevice device = mRemoteDevices.getDevice(address); if (device == null) { infoLog("No record of the device:" + device); // This device will be added as part of the BONDING_STATE_CHANGE intent processing // in sendIntent above device = mAdapter.getRemoteDevice(Utils.getAddressStringFromByte(address)); } infoLog("bondStateChangeCallback: Status: " + status + " Address: " + device + " newState: " + newState); Message msg = obtainMessage(BONDING_STATE_CHANGE); msg.obj = device; if (newState == BOND_STATE_BONDED) msg.arg1 = BluetoothDevice.BOND_BONDED; else if (newState == BOND_STATE_BONDING) msg.arg1 = BluetoothDevice.BOND_BONDING; else msg.arg1 = BluetoothDevice.BOND_NONE; msg.arg2 = status; sendMessage(msg); }
这里发送一个BONDING_STATE_CHANGE消息,
@Override public boolean processMessage(Message msg) { BluetoothDevice dev = (BluetoothDevice)msg.obj; boolean result = false; if (mDevices.contains(dev) && msg.what != CANCEL_BOND && msg.what != BONDING_STATE_CHANGE) { deferMessage(msg); return true; } switch (msg.what) { case CREATE_BOND: result = createBond(dev, false); break; case REMOVE_BOND: result = removeBond(dev, false); break; case CANCEL_BOND: result = cancelBond(dev); break; case BONDING_STATE_CHANGE: int newState = msg.arg1; int reason = getUnbondReasonFromHALCode(msg.arg2); sendIntent(dev, newState, reason); if(newState != BluetoothDevice.BOND_BONDING ) { /* this is either none/bonded, remove and transition */ result = !mDevices.remove(dev); if (mDevices.isEmpty()) { // Whenever mDevices is empty, then we need to // set result=false. Else, we will end up adding // the device to the list again. This prevents us // from pairing with a device that we just unpaired result = false; transitionTo(mStableState); } if (newState == BluetoothDevice.BOND_NONE) { // Set the profile Priorities to undefined clearProfilePriorty(dev); } else if (newState == BluetoothDevice.BOND_BONDED) { // Restore the profile priorty settings setProfilePriorty(dev); } } else if(!mDevices.contains(dev)) result=true; break; default: Log.e(TAG, "Received unhandled event:" + msg.what); return false; } if (result) mDevices.add(dev); return true; }
程序会进入case BONDING_STATE_CHANGE:分支,这里会对相应的配对结果作出相应的处理。
蓝牙的配对就分析到这里。
0 0
- Android4.4(MT8685)源码蓝牙解析--配对
- Android4.4(MT8685)源码蓝牙解析--概述
- Android4.4(MT8685)源码蓝牙解析--搜索
- Android4.4(MT8685)源码蓝牙解析--连接
- Android4.4(MT8685)源码蓝牙解析--BLE搜索
- Android4.4(MT8685)源码WIFI--初始化1
- Android4.4(MT8685)源码WIFI--初始化2
- Android4.4(MT8685)源码WIFI--扫描和连接
- Android4.4 蓝牙源码部分分析
- android源码灭屏时蓝牙自动配对
- 蓝牙配对
- 蓝牙配对
- 蓝牙基本功能源码解析
- Android蓝牙学习——搜索、配对、传文件(附源码)
- [Android源码分析]蓝牙配对之jni之上的点点滴滴
- Android4.4 Camera Gallery 分离及源码解析
- android4.4的文件管理器documentsui源码解析
- android4.4的文件管理器documentsui源码解析
- 今天放假啊约个妹子看电影啊
- 太经典了,谁编的?
- 使用 Apache Shiro 为 web 应用程序进行用户身份验证
- 武汉吉香缘公司 T6Y 飞翔
- 暴雨自救指南,你可得好好学习!
- Android4.4(MT8685)源码蓝牙解析--配对
- 胡适-答某君书
- GNU 线程创建实例
- In war-ravaged Syria, 693 people were killed;
- 从前有棵树,叫高数,树上挂了很多人……
- Q8 武汉吉香缘公司 情况
- Sql Server中日期时间格式化为字符串输出
- ASP.NET MVC 的表单提交
- UITableView -- 支持象电话本那样的按首字母索引