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