前言
我们关注蓝牙建立连接的过程
1.通信的建立一定是异步的过程,自然涉及回调
2.如果有回调,一定有一处代码进行分发处理
apk -- jni -- hal
apk的监听一定来自jni,我们关注jni的注册
解读JniCallbacks
/*
* Copyright (C) 2012-2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.bluetooth.btservice;
import android.util.Log;
final class JniCallbacks {
private RemoteDevices mRemoteDevices;
private AdapterProperties mAdapterProperties;
private AdapterState mAdapterStateMachine;
private BondStateMachine mBondStateMachine;
JniCallbacks(AdapterState adapterStateMachine,AdapterProperties adapterProperties) {
mAdapterStateMachine = adapterStateMachine;
mAdapterProperties = adapterProperties;
}
void init(BondStateMachine bondStateMachine, RemoteDevices remoteDevices) {
mRemoteDevices = remoteDevices;
mBondStateMachine = bondStateMachine;
}
void cleanup() {
mRemoteDevices = null;
mAdapterProperties = null;
mAdapterStateMachine = null;
mBondStateMachine = null;
}
@Override
public Object clone() throws CloneNotSupportedException {
throw new CloneNotSupportedException();
}
void sspRequestCallback(byte[] address, byte[] name, int cod, int pairingVariant,
int passkey) {//蓝牙芯片通知配对确认
mBondStateMachine.sspRequestCallback(address, name, cod, pairingVariant,
passkey);
}
void devicePropertyChangedCallback(byte[] address, int[] types, byte[][] val) {//用于记录蓝牙设备的数据,主要涉及的类为RemoteDevices.DeviceProperties。例如蓝牙地址 蓝牙uuid
mRemoteDevices.devicePropertyChangedCallback(address, types, val);
}
void deviceFoundCallback(byte[] address) {//扫描设备的回调
mRemoteDevices.deviceFoundCallback(address);
}
void pinRequestCallback(byte[] address, byte[] name, int cod, boolean min16Digits) {
mBondStateMachine.pinRequestCallback(address, name, cod, min16Digits);
}
void bondStateChangeCallback(int status, byte[] address, int newState) {//配对状态更改
mBondStateMachine.bondStateChangeCallback(status, address, newState);
}
void aclStateChangeCallback(int status, byte[] address, int newState) {//配置的设备状态更改,例如远程设备关闭了蓝牙,会通知出来,具体的时间是多久?
mRemoteDevices.aclStateChangeCallback(status, address, newState);
}
void stateChangeCallback(int status) {//本设备的蓝牙打开和关闭通知
mAdapterStateMachine.stateChangeCallback(status);
}
void discoveryStateChangeCallback(int state) {//扫描开始和扫描结束,开始是1 结束是0
mAdapterProperties.discoveryStateChangeCallback(state);
}
void adapterPropertyChangedCallback(int[] types, byte[][] val) {//不是很清楚用来做什么
mAdapterProperties.adapterPropertyChangedCallback(types, val);
}
}
场景:配对建立连接过程
设备端:
UI端点击配对 -- 系统服务 -- Bluetooth.apk -- jni -- hal ----> 接受方
接受方:
接受方 -- 发送pin指令进行配对 --> 设备端
设备端
设备端收到指令hal -- jni -- Bluetooth.apk -- UI端接受点击确认
JniCallbacks.sspRequestCallback 接收到回调之后,进行事件分发
案例:蓝牙配对连接
注:
配对的前提,设备已知,代码分析要从设备信息出发
1.UI调用方法
BluetoothDevice.createBond
public boolean createBond() {
······
try {
return sService.createBond(this, TRANSPORT_AUTO);//sService为Bluetooth.apk中的服务
} catch (RemoteException e) {Log.e(TAG, "", e);}
return false;
}
注:
sService的获取来自系统服务BluetoothManagerService
2.蓝牙app及jni
1)AdapterService.AdapterServiceBinder.createBond
AdapterService.AdapterServiceBinder.createBond --> AdapterService.createBond
boolean createBond(BluetoothDevice device, int transport, OobData oobData) {
······
// 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;
msg.arg1 = transport;
if (oobData != null) {
Bundle oobDataBundle = new Bundle();
oobDataBundle.putParcelable(BondStateMachine.OOBDATA, oobData);
msg.setData(oobDataBundle);
}
mBondStateMachine.sendMessage(msg);//mBondStateMachine为状态机。要熟悉状态机的运用
return true;
}
2)BondStateMachine.StableState接受来自消息CREATE_BOND
mBondStateMachine的默认状态为mStableState
private BondStateMachine(AdapterService service,
AdapterProperties prop, RemoteDevices remoteDevices) {
super("BondStateMachine:");
addState(mStableState);
addState(mPendingCommandState);
······
setInitialState(mStableState);
}
private class StableState extends State {
······
@Override
public boolean processMessage(Message msg) {
·······
switch(msg.what) {
·······
case CREATE_BOND:
OobData oobData = null;
if (msg.getData() != null)
oobData = msg.getData().getParcelable(OOBDATA);
createBond(dev, msg.arg1, oobData, true);
break;
······
}
······
}
}
private boolean createBond(BluetoothDevice dev, int transport, OobData oobData,
boolean transition) {
if (dev.getBondState() == BluetoothDevice.BOND_NONE) {
infoLog("Bond address is:" + dev);
byte[] addr = Utils.getBytesFromAddress(dev.getAddress());
boolean result;
if (oobData != null) {
result = mAdapterService.createBondOutOfBandNative(addr, transport, oobData);
} else {
result = mAdapterService.createBondNative(addr, transport);//调用jni进行通信
}
if (!result) {
sendIntent(dev, BluetoothDevice.BOND_NONE,
BluetoothDevice.UNBOND_REASON_REMOVED);
return false;
} else if (transition) {
transitionTo(mPendingCommandState);//同步把状态切换成带处理状态(mPendingCommandState)
}
return true;
}
return false;
}
3)AdapterService.createBondNative
/*package*/ native boolean createBondNative(byte[] address, int transport);
com_android_bluetooth_btservice_AdapterService.cpp
static jboolean createBondNative(JNIEnv* env, jobject obj, jbyteArray address, jint transport) {
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, transport);//通过jni调进蓝牙协议栈中
env->ReleaseByteArrayElements(address, addr, 0);
result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
return result;
}
这里是没有对应的回调传给jni,那自然是jni主动被调用,这样才能把配对的状态告知app
3.蓝牙协议栈--省略
4.Bluetooth.apk接收回调
1)关注JniCallbacks接收回调的地方
void bondStateChangeCallback(int status, byte[] address, int newState) {//配对状态更改
mBondStateMachine.bondStateChangeCallback(status, address, newState);
}
void sspRequestCallback(byte[] address, byte[] name, int cod, int pairingVariant,
int passkey) {//蓝牙芯片通知配对确认
mBondStateMachine.sspRequestCallback(address, name, cod, pairingVariant,
passkey);
}
2)BondStateMachine
a)关注配对状态的回调
void bondStateChangeCallback(int status, byte[] address, int newState) {
······
Message msg = obtainMessage(BONDING_STATE_CHANGE);//状态机目前处于mPendingCommandState
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);
}
private class PendingCommandState extends State {
······
@Override
public boolean processMessage(Message msg) {
······
switch (msg.what) {
······
case BONDING_STATE_CHANGE:
int newState = msg.arg1;
int reason = getUnbondReasonFromHALCode(msg.arg2);
sendIntent(dev, newState, reason);//发送广播出去
······
break;
······
}
······
}
}
private void sendIntent(BluetoothDevice device, int newState, int reason) {
DeviceProperties devProp = mRemoteDevices.getDeviceProperties(device);
int oldState = BluetoothDevice.BOND_NONE;
if (devProp != null) {
oldState = devProp.getBondState();
}
if (oldState == newState) return;
mAdapterProperties.onBondStateChanged(device, newState);
Intent intent = new Intent(BluetoothDevice.ACTION_BOND_STATE_CHANGED);//关注广播
intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
intent.putExtra(BluetoothDevice.EXTRA_BOND_STATE, newState);
intent.putExtra(BluetoothDevice.EXTRA_PREVIOUS_BOND_STATE, oldState);
if (newState == BluetoothDevice.BOND_NONE)
intent.putExtra(BluetoothDevice.EXTRA_REASON, reason);
mAdapterService.sendBroadcastAsUser(intent, UserHandle.ALL,
AdapterService.BLUETOOTH_PERM);
infoLog("Bond State Change Intent:" + device + " OldState: " + oldState
+ " NewState: " + newState);
}
总结:
针对配对的状态,其他应用关注广播:BluetoothDevice.ACTION_BOND_STATE_CHANGED
b)关注配置过程确认pin码
void sspRequestCallback(byte[] address, byte[] name, int cod, int pairingVariant,
int passkey) {
······
Message msg = obtainMessage(SSP_REQUEST);//状态机目前处于mPendingCommandState
msg.obj = device;
if(displayPasskey)
msg.arg1 = passkey;
msg.arg2 = variant;
sendMessage(msg);
}
private class PendingCommandState extends State {
······
@Override
public boolean processMessage(Message msg) {
······
switch (msg.what) {
······
case SSP_REQUEST:
int passkey = msg.arg1;
int variant = msg.arg2;
sendDisplayPinIntent(devProp.getAddress(), passkey, variant);//发送广播
break;
······
}
······
}
}
private void sendDisplayPinIntent(byte[] address, int pin, int variant) {
Intent intent = new Intent(BluetoothDevice.ACTION_PAIRING_REQUEST);//关注此广播
intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mRemoteDevices.getDevice(address));
if (pin != 0) {
intent.putExtra(BluetoothDevice.EXTRA_PAIRING_KEY, pin);
}
intent.putExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT, variant);
intent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
mAdapterService.sendOrderedBroadcast(intent, mAdapterService.BLUETOOTH_ADMIN_PERM);
}
总结:
针对配对过程获取pin码,其他应用关注广播:BluetoothDevice.ACTION_PAIRING_REQUEST
参考学习
https://www.jianshu.com/p/a150d55e29ca
https://blog.csdn.net/WHB20081815/article/details/88653177
网友评论