packages\apps\Settings\src\com\android\settings\bluetooth\BluetoothPairingDetail.java
@Override
void onDevicePreferenceClick(BluetoothDevicePreference btPreference) {
disableScanning();
super.onDevicePreferenceClick(btPreference);
} packages\apps\Settings\src\com\android\settings\bluetooth\DeviceListPreferenceFragment.java
void onDevicePreferenceClick(BluetoothDevicePreference btPreference) {
btPreference.onClicked();
} packages\apps\Settings\src\com\android\settings\bluetooth\BluetoothDevicePreference.java
void onClicked() {
Context context = getContext();
// 获取连接状态
int bondState = mCachedDevice.getBondState(); final MetricsFeatureProvider metricsFeatureProvider =
FeatureFactory.getFactory(context).getMetricsFeatureProvider();
// 已经连接
if (mCachedDevice.isConnected()) {
// 断开连接
metricsFeatureProvider.action(context,
MetricsEvent.ACTION_SETTINGS_BLUETOOTH_DISCONNECT);
askDisconnect();
// 以前连接过,不需要再配对,直接进行连接
} else if (bondState == BluetoothDevice.BOND_BONDED) {
metricsFeatureProvider.action(context,
MetricsEvent.ACTION_SETTINGS_BLUETOOTH_CONNECT);
mCachedDevice.connect(true);
// 没连接过,进行配对,需要连接的双方都同意之后才能连接
} else if (bondState == BluetoothDevice.BOND_NONE) {
metricsFeatureProvider.action(context,
MetricsEvent.ACTION_SETTINGS_BLUETOOTH_PAIR);
if (!mCachedDevice.hasHumanReadableName()) {
metricsFeatureProvider.action(context,
MetricsEvent.ACTION_SETTINGS_BLUETOOTH_PAIR_DEVICES_WITHOUT_NAMES);
}
pair();
}
} 1. 已经连接过的设备,直接断开
// Show disconnect confirmation dialog for a device.
private void askDisconnect() {
Context context = getContext();
String name = mCachedDevice.getName();
if (TextUtils.isEmpty(name)) {
name = context.getString(R.string.bluetooth_device);
}
String message = context.getString(R.string.bluetooth_disconnect_all_profiles, name);
String title = context.getString(R.string.bluetooth_disconnect_title);
// 对话框的listener
DialogInterface.OnClickListener disconnectListener = new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
mCachedDevice.disconnect();
}
};
// 显示断开对话框
mDisconnectDialog = Utils.showDisconnectDialog(context,
mDisconnectDialog, disconnectListener, title, Html.fromHtml(message));
} 2. 匹配过的设别,进行连接
frameworks\base\packages\SettingsLib\src\com\android\settingslib\bluetooth\CachedBluetoothDevice.java
public void connect(boolean connectAllProfiles) {
// 是否配对过
if (!ensurePaired()) {
return;
} mConnectAttempted = SystemClock.elapsedRealtime();
connectWithoutResettingTimer(connectAllProfiles);
} private void connectWithoutResettingTimer(boolean connectAllProfiles) {
// Try to initialize the profiles if they were not.
if (mProfiles.isEmpty()) {
// if mProfiles is empty, then do not invoke updateProfiles. This causes a race
// condition with carkits during pairing, wherein RemoteDevice.UUIDs have been updated
// from bluetooth stack but ACTION.uuid is not sent yet.
// Eventually ACTION.uuid will be received which shall trigger the connection of the
// various profiles
// If UUIDs are not available yet, connect will be happen
// upon arrival of the ACTION_UUID intent.
Log.d(TAG, "No profiles. Maybe we will connect later");
return;
} // Reset the only-show-one-error-dialog tracking variable
mIsConnectingErrorPossible = true; int preferredProfiles = 0;
for (LocalBluetoothProfile profile : mProfiles) {
// connectAllProfile传进来的是true
if (connectAllProfiles ? profile.isConnectable() : profile.isAutoConnectable()) {
if (profile.isPreferred(mDevice)) {
++preferredProfiles;
connectInt(profile); // 连接对应的profile
}
}
}
if (DEBUG) Log.d(TAG, "Preferred profiles = " + preferredProfiles); if (preferredProfiles == 0) {
connectAutoConnectableProfiles();
}
} private void connectAutoConnectableProfiles() {
if (!ensurePaired()) {
return;
}
// Reset the only-show-one-error-dialog tracking variable
mIsConnectingErrorPossible = true; for (LocalBluetoothProfile profile : mProfiles) {
if (profile.isAutoConnectable()) {
profile.setPreferred(mDevice, true);
connectInt(profile);
}
}
} 3. 没有配对的设备,先进行配对
private void pair() {
if (!mCachedDevice.startPairing()) {
Utils.showError(getContext(), mCachedDevice.getName(),
R.string.bluetooth_pairing_error_message);
}
} frameworks\base\packages\SettingsLib\src\com\android\settingslib\bluetooth\CachedBluetoothDevice.java
public boolean startPairing() {
// Pairing is unreliable while scanning, so cancel discovery
// 配对的时候,关闭扫描
if (mLocalAdapter.isDiscovering()) {
mLocalAdapter.cancelDiscovery();
} if (!mDevice.createBond()) {
return false;
} return true;
} frameworks\base\core\java\android\bluetooth\BluetoothDevice.java
@RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
public boolean createBond() {
final IBluetooth service = sService;
if (service == null) {
Log.e(TAG, "BT not enabled. Cannot create bond to Remote Device");
return false;
}
try {
Log.i(TAG, "createBond() for device " + getAddress()
+ " called by pid: " + Process.myPid()
+ " tid: " + Process.myTid());
return service.createBond(this, TRANSPORT_AUTO);
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
return false;
} packages\apps\Bluetooth\src\com\android\bluetooth\btservice\AdapterService.java
private static class AdapterServiceBinder extends IBluetooth.Stub {
public boolean createBond(BluetoothDevice device, int transport) {
if (!Utils.checkCallerAllowManagedProfiles(mService)) {
Log.w(TAG, "createBond() - Not allowed for non-active user");
return false;
} AdapterService service = getService();
if (service == null) return false;
return service.createBond(device, transport, null); // bond
} // 建立bond
boolean createBond(BluetoothDevice device, int transport, OobData oobData) {
enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
"Need BLUETOOTH ADMIN permission");
DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
if (deviceProp != null && deviceProp.getBondState() != BluetoothDevice.BOND_NONE) {
return false;
}
// 在多播的时候不要进行bond,不明白这个multicast是什么意思
// Multicast: Do not allow bonding while multcast
A2dpService a2dpService = A2dpService.getA2dpService();
if (a2dpService != null &&
a2dpService.isMulticastFeatureEnabled() &&
a2dpService.isMulticastOngoing(null)) {
Log.i(TAG,"A2dp Multicast is ongoing, ignore bonding");
return false;
} mRemoteDevices.setBondingInitiatedLocally(Utils.getByteAddress(device)); // Pairing is unreliable while scanning, so cancel discovery
// Note, remove this when native stack improves
if (!mAdapterProperties.isDiscovering()) {
Log.i(TAG,"discovery not active, no need to send cancelDiscovery");
} else {
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);
return true;
} packages\apps\Bluetooth\src\com\android\bluetooth\btservice\BondStateMachine.java
private class StableState extends State {
@Override
public void enter() {
infoLog("StableState(): Entering Off State");
} @Override
public synchronized boolean processMessage(Message msg) { BluetoothDevice dev = (BluetoothDevice)msg.obj; 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;
case REMOVE_BOND:
removeBond(dev, true);
break;
case BONDING_STATE_CHANGE:
int newState = msg.arg1;
/* if incoming pairing, transition to pending state */
if (newState == BluetoothDevice.BOND_BONDING)
{
if(!mDevices.contains(dev)) {
mDevices.add(dev);
}
sendIntent(dev, newState, 0);
transitionTo(mPendingCommandState);
}
else if (newState == BluetoothDevice.BOND_NONE)
{
/* if the link key was deleted by the stack */
sendIntent(dev, newState, 0);
}
else
{
Log.e(TAG, "In stable state, received invalid newState: " + newState);
}
break; case CANCEL_BOND:
default:
Log.e(TAG, "Received unhandled state: " + msg.what);
return false;
}
return true;
}
} private boolean createBond(BluetoothDevice dev, int transport, OobData oobData,
boolean transition) {
if(mAdapterService == null) return false;
if (dev.getBondState() == BluetoothDevice.BOND_NONE) {
infoLog("Bond address is:" + dev);
byte[] addr = Utils.getBytesFromAddress(dev.getAddress());
boolean result;
// 调用JNI
if (oobData != null) {
result = mAdapterService.createBondOutOfBandNative(addr, transport, oobData);
} else {
result = mAdapterService.createBondNative(addr, transport);
} if (!result) {
sendIntent(dev, BluetoothDevice.BOND_NONE,
BluetoothDevice.UNBOND_REASON_REMOVED);
return false;
} else if (transition) {
transitionTo(mPendingCommandState);
}
return true;
}
return false;
}

Liu Tao

2019-3-27

Android 8 蓝牙 连接过程的更多相关文章

  1. Android使用蓝牙连接adb调试App

    使用WiFi连接Android设备调试APP的教程非常多,可是项目中须要使用蓝牙进行通信.所以牵扯使用蓝牙调用adb. 1.   将电脑蓝牙与手机进行配对(控制面板->设备和打印机->加入 ...

  2. Android 8 蓝牙打开过程

    packages\apps\Settings\src\com\android\settings\bluetooth\BluetoothEnabler.java @Override public boo ...

  3. Android实现蓝牙耳机连接

    代码地址如下:http://www.demodashi.com/demo/13259.html 前言 讲讲android对于蓝牙耳机连接技术的实现 今天涉及的内容有: 流程讲解 新建广播Bluetoo ...

  4. 基于swift语言iOS8的蓝牙连接(初步)

    看过一些蓝牙App的事例,大体上对蓝牙的连接过程进行了了解.但是开始真正自己写一个小的BLE程序的时候就举步维艰了.那些模棱两可的概念在头脑中瞬间就蒸发了,所以还是决定从最基本的蓝牙连接过程进行.这里 ...

  5. ZT Android 4.2 BT系统之蓝牙关闭过程全跟踪

    Android 4.2 BT系统之蓝牙关闭过程全跟踪 分类: android 2013-08-03 00:34 2252人阅读 评论(10) 收藏 举报 代码位置:       frameworks/ ...

  6. Android蓝牙连接自动测试工具

    蓝牙连接自动测试工具 1.需求产生 开发不按着需求走都是耍流氓且浪费时间.此工具的需求产生是研发人员在开发产品时涉及到蓝牙驱动和安卓蓝牙两个东西.但是呢,蓝牙不太稳定,那么工作来了.就需要研发人员一边 ...

  7. ubuntu16.04连接android手机蓝牙共享网络热点

    最近的想要用android手机蓝牙共享wifi网络给ubuntu16.04系统用,查了好多资料,发现网上很少有有用的.自己实践后分享如下. 第一步:手机与电脑配对:         该步骤比较简单,网 ...

  8. Android Multimedia框架总结(十九)Camera2框架C/S模型之CameraService启动及与Client连接过程

    转载请把头部出处链接和尾部二维码一起转载,本文出自逆流的鱼yuiop:http://blog.csdn.net/hejjunlin/article/details/53150322 Agenda: 一 ...

  9. Android一对多蓝牙连接示例APP

    一对多蓝牙连接示例,基于Google BluetoothChat修改,实现一对多聊天(一个服务端.多个客户端),类似聊天室. 主要功能: 客户端的发出的消息所有终端都能收到(由服务端转发) 客户端之间 ...

随机推荐

  1. [CC-BLREDSET]Black and Red vertices of Tree

    [CC-BLREDSET]Black and Red vertices of Tree 题目大意: 有一棵\(n(\sum n\le10^6)\)个结点的树,每个结点有一种颜色(红色.黑色.白色).删 ...

  2. 通过echarts的demo

    通过最近两天对echarts的了解,下面用echarts.js写了一个小效果: 效果的demo为: <!DOCTYPE html> <html lang="en" ...

  3. Express基础单词

    访问请求对象(request)或(req) 响应对象(response)或(res) 中间件(middleware) http的请求方法(method) 服务器的路径(path) 路由匹配时的函数(c ...

  4. 转:2016年崛起的js项目

    近几年 JS 社区创新和演化的速度是有目共睹的,几个月前比较时髦的技术很可能现在已经过时了. 2016 已经过去,你有没有担心错过了什么重要的内容?在这篇调查报告中我们会为你解读社区的主流趋势. 我们 ...

  5. 杭电acm2059-龟兔赛跑 java

    一看题就知道是动态规划,不过这要看下如何设置变化数组了 先分析这道题:兔子到达终点的时间时固定的,因此只需要考虑乌龟了,乌龟骑电车和骑自行车的时间,然后计算,因为中间有N个充电站,可以看做N个点(到起 ...

  6. sqlmap简单使用

    就以实验吧上那个简单的sql注入题为例吧,不过那道题确实经典,把sqlmap的整个使用过程都展现了一遍,先奉上那道题的地址:http://ctf5.shiyanbar.com/web/index_3. ...

  7. 微信小程序中的单位

    vw:viewpoint width,视窗宽度,1vw等于视窗宽度的1%. vh:viewpoint height,视窗高度,1vh等于视窗高度的1%. rpx:rpx单位是微信小程序中css的尺寸单 ...

  8. openstack 之~keystone之网关协议

    第一:静态页面和动态页面 上一篇博客介绍了HTTP后,我们知道一个web server的本质就是 浏览器发送一个HTTP请求: 服务器收到请求,生成一个HTML文档: 服务器把HTML文档作为HTTP ...

  9. javaScript系列 [03]-javaScript原型对象

    [03]-javaScript原型对象 引用: javaScript是一门基于原型的语言,它允许对象通过原型链引用另一个对象来构建对象中的复杂性,JavaScript使用原型链这种机制来实现动态代理. ...

  10. app保存图片到用户相册时闪退解决办法

    在iOS11中,app保存图片到用户相册时必须添加权限使用描述即NSPhotoLibraryAddUsageDescription,否则会闪退. 只需在info.plist—Property List ...