[Android源码分析]蓝牙配对之jni之上的点点滴滴



    在之前晓东已经和大家分析完成了蓝牙打开和蓝牙搜索的过程了,在搜索到设备的下一步我们要做的就是蓝牙的配对了。本文晓东将和大家一起来看看蓝牙配对究竟涉及到了哪些内容。

         1UI上的点击设备开始

    在android中,对设备的点击都是在onclicked函数中实现的,所以我们就从这个函数开始分析了:


//对对应设备点击之后的操作
    void onClicked() {
        int bondState = mCachedDevice.getBondState();
        //若是该设备已经连接了,就断开连接
        if (mCachedDevice.isConnected()) {
            askDisconnect();
        } else {
            // Single link version, reject the second connect request
            if (mLocalAdapter.isSingleLinkVersion() == true &&
                    mLocalAdapter.getAdapterConnectionState() != BluetoothAdapter.STATE_DISCONNECTED) {
                Context context = getContext();
                String toastMsg = context.getString(R.string.bluetooth_single_slave_pair_only_device);
                Toast.makeText(getContext(), toastMsg, Toast.LENGTH_SHORT).show();
                return;
            }

        //若是已经配对过了,就开始连接
            if (bondState == BluetoothDevice.BOND_BONDED) {
                mCachedDevice.connect(true);
        //若是还没有配对,则开始配对
            } else if (bondState == BluetoothDevice.BOND_NONE) {
                pair();
            }
        }
}

所以,其实同样一个点击在设备处于不同状态下是有不同操作的,毫无疑问,最开始我们总是位于最初的状态,这个时候的点击就是开始配对了。我们去看看配对是怎么做的:

private void pair() {
        //开始配对
        if (!mCachedDevice.startPairing()) {
        //配对出问题,显示error信息
            Utils.showError(getContext(), mCachedDevice.getName(),
                    R.string.bluetooth_pairing_error_message);
        }
    }

调动的是startpairing函数来实现真正的配对操作:

 boolean startPairing() {
        // Pairing is unreliable while scanning, so cancel discovery
        //若是正在扫描,就先cancel掉扫描操作
        if (mLocalAdapter.isDiscovering()) {
            mLocalAdapter.cancelDiscovery();
        }
        //开始配对,这就到framework层了
        if (!mDevice.createBond()) {
            return false;
        }
        //配对后自动连接
        mConnectAfterPairing = true;  // auto-connect after pairing
        return true;
    }

2framework层的配对操作分析

    上面的操作会真正调用下面这个framework的函数:

public synchronized boolean createBond(String address) {
        //看是否可以配对?比如有没有设备正在配对之类
        if (!isBondingFeasible(address)) return false;
        //开始配对。timeout是1分钟,详细分析见4
        if (!createPairedDeviceNative(address, 60000  /*1 minute*/ )) {
            return false;
        }
        //把这个地址赋值到pendingoutgonigbonding中
        mBondState.setPendingOutgoingBonding(address);
			//设置状态为bonding
        mBondState.setBondState(address, BluetoothDevice.BOND_BONDING);
        return true;
    }

3、状态改变到bonding的分析

         设置bond的状态

    /*package*/ synchronized boolean setBondState(String address, int state) {
        return setBondState(address, state, 0);
    }

    /*package*/ synchronized boolean setBondState(String address, int state, int reason) {
        mBondState.setBondState(address.toUpperCase(), state, reason);
        return true;
}

    public synchronized void setBondState(String address, int state) {
        setBondState(address, state, 0);
    }

    /** reason is ignored unless state == BOND_NOT_BONDED */
    public synchronized void setBondState(String address, int state, int reason) {
        if (DBG) Log.d(TAG, "setBondState " + "address" + " " + state + "reason: " + reason);
    //检查状态是否真的改变
        int oldState = getBondState(address);
        if (oldState == state) {
            return;
        }

        // Check if this was an pending outgoing bonding.
        // If yes, reset the state.
        //看是不是从bonding的状态变化的,若是,则把mPendingOutgoingBonding位清空
        if (oldState == BluetoothDevice.BOND_BONDING) {
            if (address.equals(mPendingOutgoingBonding)) {
                mPendingOutgoingBonding = null;
            }
        }
        if (state == BluetoothDevice.BOND_BONDED) {
            boolean setTrust = false;
            if (mPairingRequestRcvd.contains(address)) setTrust = true;

            mService.addProfileState(address, setTrust);
            mPairingRequestRcvd.remove(address);

        } else if (state == BluetoothDevice.BOND_BONDING) {
                //若是bonding,则先得到a2dpproxy和headsetproxy,这个是为了后面的连接做准备的
            if (mA2dpProxy == null || mHeadsetProxy == null) {
                getProfileProxy();
            }
        } else if (state == BluetoothDevice.BOND_NONE) {
            mPairingRequestRcvd.remove(address);
        }

        //主要是bonded和none的处理,我们暂时不看
        setProfilePriorities(address, state);

        if (DBG) {
            Log.d(TAG, address + " bond state " + oldState + " -> " + state
                + " (" + reason + ")");
        }

3.1 getProfileProxy的分析

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

        //新建对应profile
        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.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.HEALTH) {
            BluetoothHealth health = new BluetoothHealth(context, listener);
            return true;
        } else {
            return false;
        }
    }

a2dp为例,就是返回对应的类

 /*package*/ BluetoothA2dp(Context mContext, ServiceListener l) {
        IBinder b = ServiceManager.getService(BluetoothA2dpService.BLUETOOTH_A2DP_SERVICE);
        mServiceListener = l;
        mAdapter = BluetoothAdapter.getDefaultAdapter();
        if (b != null) { 
        //得到对应的service
            mService = IBluetoothA2dp.Stub.asInterface(b);
            if (mServiceListener != null) {
                //返回this
                mServiceListener.onServiceConnected(BluetoothProfile.A2DP, this);
            }
        } else {
            Log.w(TAG, "Bluetooth A2DP service not available!");

            // Instead of throwing an exception which prevents people from going
            // into Wireless settings in the emulator. Let it crash later when it is actually used.
            mService = null;
        }
    }


所以,总得来说在jni之上,配对并没有做太多的东西,就是调用对应的配对的jni之下的函数。

若您觉得该文章对您有帮助,请在下面用鼠标轻轻按一下“顶”,哈哈~~·





你可能感兴趣的:(android,蓝牙,配对)