内容简介:本文详细分析了android4.0 中蓝牙使能的过程,相比较android2.3,4.0中的蓝牙最大的差别在于UI上on/off的伪开关。在android4.0中加入了 adapter的状态机。所谓的状态机就类似于状态转换图,在一个状态收到某个特定的命令会变成另外一个状态,不同的命令可以跳转到不同的状态(当然也有 可能到同一状态)。adapter的初始状态为poweroff,在android系统启动的时候会进入warmup状态,同时会进行UUID的add, 该操作会引起propertychanged的UUID signal,该signal会使得状态从warmup变换到hotoff状态。因此在UI端off时其实adapter已经处于hotoff状态而不是 poweroff状态。这一点是很关键的。在正文中,我会从假如我不知道这些开始来描绘整个使能的过程。
正文:
毫无疑问,bluetooth的打开是在Settings中进行的操作。因此,冤有头,债有主,我们来到了Settings.java中,果然发现了相关的代码如下:
mBluetoothEnabler =new BluetoothEnabler(context, new Switch(context));
于是,我们得以进入真正的蓝牙操作的殿堂,好好进去看看吧。
1 1、BluetoothEnabler的构造函数 2 3 4 5 public BluetoothEnabler(Context context,Switch switch_) { 6 7 mContext = context; 8 9 mSwitch = switch_; 10 11 //很简单了,去调用一个LocalBluetoothManager类的getInstance,其实会构造该类的 12 13 LocalBluetoothManager manager =LocalBluetoothManager.getInstance(context); 14 15 if (manager == null) { 16 17 // Bluetooth is not supported 18 19 mLocalAdapter = null; 20 21 mSwitch.setEnabled(false); 22 23 } else { 24 25 //构造成功后,通过manager得到bluetooth的adapter 26 27 mLocalAdapter =manager.getBluetoothAdapter(); 28 29 } 30 31 //同时新建一个intent,用于接收ACTION_STATE_CHANGED 32 33 mIntentFilter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED); 34 35 } 36 37 38 39 2、LocalBluetoothManager类的getInstance 40 41 public static synchronized LocalBluetoothManager getInstance(Context context) { 42 43 if (sInstance == null) { 44 45 //2.1同样的,这个会去调用LocalBluetoothAdapter的getInstance,也会构造该类 46 47 LocalBluetoothAdapter adapter =LocalBluetoothAdapter.getInstance(); 48 49 if (adapter == null) { 50 51 return null; 52 53 } 54 55 // This will be around as long asthis process is 56 57 Context appContext =context.getApplicationContext(); 58 59 //2.2构造LocalBluetoothManager类 60 61 sInstance = new LocalBluetoothManager(adapter, appContext); 62 63 } 64 65 66 67 return sInstance; 68 69 } 70 71 2.1 LocalBluetoothAdapter的getInstance 72 73 74 75 static synchronized LocalBluetoothAdapter getInstance() { 76 77 if (sInstance == null) { 78 79 //2.1.1通过BluetoothAdapter得到DefaultAdapter 80 81 BluetoothAdapter adapter =BluetoothAdapter.getDefaultAdapter(); 82 83 if (adapter != null) { 84 85 //2.1.2若有该DefaultAdapter,则构造LocalBluetoothAdapter 86 87 sInstance = new LocalBluetoothAdapter(adapter); 88 89 } 90 91 } 92 93 94 95 return sInstance; 96 97 } 98 99 100 101 2.1.1BluetoothAdapter得到DefaultAdapter 102 103 104 105 public static synchronized BluetoothAdapter getDefaultAdapter() { 106 107 if (sAdapter == null) { 108 109 IBinder b =ServiceManager.getService(BluetoothAdapter.BLUETOOTH_SERVICE); 110 111 if (b != null) { 112 113 IBluetooth service =IBluetooth.Stub.asInterface(b); 114 115 sAdapter = new BluetoothAdapter(service); 116 117 } 118 119 } 120 121 return sAdapter; 122 123 } 124 125 126 127 2.1.2构造LocalBluetoothAdapter 128 129 //其实就是 mAdapter的初始化而已 130 131 private LocalBluetoothAdapter(BluetoothAdapter adapter) { 132 133 mAdapter = adapter; 134 135 } 136 137 2.2构造LocalBluetoothManager类 138 139 //管理本地蓝牙类,用来在蓝牙API子类上面再封装一个接口 140 141 private LocalBluetoothManager(LocalBluetoothAdapter adapter, Context context) { 142 143 mContext = context; 144 145 //mLocalAdapter初始化为DefaultAdapter中得到的值 146 147 mLocalAdapter= adapter; 148 149 //构造CachedBluetoothDeviceManager,用来管理远程蓝牙设备 150 151 mCachedDeviceManager = new CachedBluetoothDeviceManager(context); 152 153 //2.2.1构建BluetoothEventManager,该类是用来管理广播消息和回调函数的,即分发不同的消息去对UI进行处理 154 155 mEventManager = new BluetoothEventManager(mLocalAdapter, 156 157 mCachedDeviceManager, context); 158 159 //2.2.2该类提供对不同LocalBluetoothProfile object的访问 160 161 mProfileManager = new LocalBluetoothProfileManager(context, 162 163 mLocalAdapter,mCachedDeviceManager, mEventManager); 164 165 } 166 167 168 169 2.2.1构建BluetoothEventManager 170 171 172 173 BluetoothEventManager(LocalBluetoothAdapteradapter, 174 175 CachedBluetoothDeviceManagerdeviceManager, Context context) { 176 177 mLocalAdapter = adapter; 178 179 mDeviceManager = deviceManager; 180 181 //创建两个IntentFilter 182 183 mAdapterIntentFilter = new IntentFilter(); 184 185 //这里没有对mProfileIntentFilter进行初始化,这个在LocalBluetoothProfileManager的addProfile中实现 186 187 mProfileIntentFilter = new IntentFilter(); 188 189 //创建一个Handler的Hash表 190 191 mHandlerMap = new HashMap<String,Handler>(); 192 193 mContext = context; 194 195 196 197 //注册对adapter和Device的几个广播消息的处理回调函数 198 199 //add action到mAdapterIntentFilter 200 201 // Bluetooth on/off broadcasts 202 203 addHandler(BluetoothAdapter.ACTION_STATE_CHANGED, newAdapterStateChangedHandler()); 204 205 206 207 // Discovery broadcasts 208 209 addHandler(BluetoothAdapter.ACTION_DISCOVERY_STARTED, newScanningStateChangedHandler(true)); 210 211 addHandler(BluetoothAdapter.ACTION_DISCOVERY_FINISHED, newScanningStateChangedHandler(false)); 212 213 addHandler(BluetoothDevice.ACTION_FOUND, new DeviceFoundHandler()); 214 215 addHandler(BluetoothDevice.ACTION_DISAPPEARED, newDeviceDisappearedHandler()); 216 217 addHandler(BluetoothDevice.ACTION_NAME_CHANGED, newNameChangedHandler()); 218 219 220 221 // Pairing broadcasts 222 223 addHandler(BluetoothDevice.ACTION_BOND_STATE_CHANGED, newBondStateChangedHandler()); 224 225 addHandler(BluetoothDevice.ACTION_PAIRING_CANCEL, newPairingCancelHandler()); 226 227 228 229 // Fine-grained state broadcasts 230 231 addHandler(BluetoothDevice.ACTION_CLASS_CHANGED, newClassChangedHandler()); 232 233 addHandler(BluetoothDevice.ACTION_UUID,new UuidChangedHandler()); 234 235 236 237 // Dock event broadcasts 238 239 addHandler(Intent.ACTION_DOCK_EVENT,new DockEventHandler()); 240 241 //mAdapterIntentFilter的接收处理函数 242 243 mContext.registerReceiver(mBroadcastReceiver, mAdapterIntentFilter); 244 245 } 246 247 248 249 2.2.2构造LocalBluetoothProfileManager类 250 251 252 253 LocalBluetoothProfileManager(Contextcontext, 254 255 LocalBluetoothAdapter adapter, 256 257 CachedBluetoothDeviceManagerdeviceManager, 258 259 BluetoothEventManager eventManager){ 260 261 mContext = context; 262 263 264 265 //各个类之间进行关联 266 267 mLocalAdapter = adapter; 268 269 mDeviceManager = deviceManager; 270 271 mEventManager = eventManager; 272 273 // pass this reference to adapter andevent manager (circular dependency) 274 275 mLocalAdapter.setProfileManager(this); 276 277 mEventManager.setProfileManager(this); 278 279 280 281 ParcelUuid[] uuids =adapter.getUuids(); 282 283 284 285 // uuids may be null if Bluetooth isturned off 286 287 if (uuids != null) { 288 289 //假如已经有了uuid,根据uuid来add并new对应的profile,只针对A2DP,HFP,HSP,OPP四个profile,HID和PAN在下面,每次都add 290 291 updateLocalProfiles(uuids); 292 293 } 294 295 296 297 // Always add HID and PAN profiles 298 299 //加入HID和PAN两个profile 300 301 mHidProfile = new HidProfile(context,mLocalAdapter); 302 303 addProfile(mHidProfile,HidProfile.NAME, 304 305 BluetoothInputDevice.ACTION_CONNECTION_STATE_CHANGED); 306 307 308 309 mPanProfile = new PanProfile(context); 310 311 addPanProfile(mPanProfile,PanProfile.NAME, 312 313 BluetoothPan.ACTION_CONNECTION_STATE_CHANGED); 314 315 316 317 Log.d(TAG,"LocalBluetoothProfileManager construction complete"); 318 319 } 320 321 322 好吧,其实我们被骗了,刚刚只是一个路引,不是真正的操作,真正的操作向来都是从你滑动界面那个on/off键开始的,因此我们决定把这个键的处理给揪出来。在Settings界面上一共就只有两个on/off键,一个是wifi,另一个就是蓝牙了,我们从这个代码入手: 324 325 case HEADER_TYPE_SWITCH: 326 327 //其实写这个代码的人也比较心虚,假如switch多一点,下面就要重写了 328 329 // Would need a differenttreatment if the main menu had more switches 330 331 if (header.id ==R.id.wifi_settings) { 332 333 mWifiEnabler.setSwitch(holder.switch_); 334 335 } else { 336 337 //这个就是处理了,上面的路引没有白做啊 338 339 mBluetoothEnabler.setSwitch(holder.switch_); 340 341 } 342 343 344 345 3、mBluetoothEnabler.setSwitch分析 346 347 348 349 public void setSwitch(Switch switch_) { 350 351 //若是和上次相同,则不做任何事情,可以理解,代码也懒嘛 352 353 if (mSwitch == switch_) return; 354 355 //把上次的switch的changelistener清空 356 357 mSwitch.setOnCheckedChangeListener(null); 358 359 mSwitch = switch_; 360 361 //重设这次的switch的changelistener 362 363 mSwitch.setOnCheckedChangeListener(this); 364 365 366 367 int bluetoothState =BluetoothAdapter.STATE_OFF; 368 369 //获取getBluetoothState,这个过程也会同步一下state,防止改变 370 371 if (mLocalAdapter != null)bluetoothState = mLocalAdapter.getBluetoothState(); 372 373 //根据状态设置一下两个标志位 374 375 boolean isOn = bluetoothState == BluetoothAdapter.STATE_ON; 376 377 boolean isOff = bluetoothState == BluetoothAdapter.STATE_OFF; 378 379 //设置checked的状态位。注意,假如这里状态发生了改变,则会调用this.onCheckedChanged来进行处理 380 381 mSwitch.setChecked(isOn); 382 383 if(WirelessSettings.isRadioAllowed(mContext, Settings.System.RADIO_BLUETOOTH)) { 384 385 //有bluetooth或者不是airplane,则该switch不变灰,否则,灰的。 386 387 mSwitch.setEnabled(isOn || isOff); 388 389 } else { 390 391 mSwitch.setEnabled(false); 392 393 } 394 395 } 396 397 398 399 4、onCheckedChanged 400 401 在switch状态发生改变后,会调用这个地方的回调函数进行处理。 402 403 404 405 public void onCheckedChanged(CompoundButtonbuttonView, boolean isChecked) { 406 407 // Show toast message if Bluetooth isnot allowed in airplane mode 408 409 //若是打开的话,就需要检查一下是否allow Bluetooth(radio,airplane的check) 410 411 if (isChecked && 412 413 !WirelessSettings.isRadioAllowed(mContext,Settings.System.RADIO_BLUETOOTH)) { 414 415 Toast.makeText(mContext,R.string.wifi_in_airplane_mode, Toast.LENGTH_SHORT).show(); 416 417 // Reset switch to off 418 419 //若是不对的话,reset为off 420 421 buttonView.setChecked(false); 422 423 } 424 425 426 427 if (mLocalAdapter != null) { 428 429 //4.1设置scanmode,放心,它会判断state的,不是STATE_ON,会直接返回false的 430 431 mLocalAdapter.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE); 432 433 //4.2使能或不使能Bluetooth了 434 435 mLocalAdapter.setBluetoothEnabled(isChecked); 436 437 } 438 439 //过程中还是会反灰,直到setBluetoothEnabled的结果返回会改变switch的状态 440 441 mSwitch.setEnabled(false); 442 443 } 444 445 446 447 4.1设置scanmod 448 449 450 451 会调用adapter中的setScanMode,直接去看就可以了,事实上就是设置了两个property标志,没什么 452 453 454 455 public boolean setScanMode(int mode) { 456 457 //这里把这个代码写出来就是证明一下,STATE_ON才会真正做下去,否则免谈 458 459 if (getState() != STATE_ON) returnfalse; 460 461 //这里会调用对应server中的setScanMode 462 463 return setScanMode(mode, 120); 464 465 } 466 467 468 469 public synchronized boolean setScanMode(intmode, int duration) { 470 471 //这里有个permission,好像和2.3中不一样,注意一下 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS, 472 473 "NeedWRITE_SECURE_SETTINGS permission"); 474 475 boolean pairable; 476 477 boolean discoverable; 478 479 480 481 switch (mode) { 482 483 case BluetoothAdapter.SCAN_MODE_NONE: 484 485 pairable = false; 486 487 discoverable = false; 488 489 break; 490 491 caseBluetoothAdapter.SCAN_MODE_CONNECTABLE: 492 493 //开始就是这里了,可pairable,但是不可discoverable 494 495 pairable = true; 496 497 discoverable = false; 498 499 break; 500 501 caseBluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE: 502 503 pairable = true; 504 505 discoverable = true; 506 507 if (DBG) Log.d(TAG, "BTDiscoverable for " + duration + " seconds"); 508 509 break; 510 511 default: 512 513 Log.w(TAG, "Requested invalidscan mode " + mode); 514 515 return false; 516 517 } 518 519 520 521 //设置这两个property标志 522 523 setPropertyBoolean("Discoverable", discoverable); 524 525 setPropertyBoolean("Pairable", pairable); 526 527 return true; 528 529 } 530 531 532 533 4.2setBluetoothEnabled分析 534 535 536 537 public void setBluetoothEnabled(booleanenabled) { 538 539 //根据enabled的标志设置是enable还是disable,在2.3中,这个地方就是bt_enable哦,这里还不知道,我们在第5步进行详细的分析 540 541 boolean success = enabled 542 543 ? mAdapter.enable() 544 545 : mAdapter.disable(); 546 547 //成功了,设置对应的状态位 548 549 if (success) { 550 551 setBluetoothStateInt(enabled 552 553 ?BluetoothAdapter.STATE_TURNING_ON 554 555 :BluetoothAdapter.STATE_TURNING_OFF); 556 557 } else { 558 559 if (Utils.V) { 560 561 Log.v(TAG,"setBluetoothEnabled call, manager didn't return " + 562 563 "success forenabled: " + enabled); 564 565 } 566 567 //同步一下设置的状态 568 569 syncBluetoothState(); 570 571 } 572 573 } 574 575 } 576 577 578 579 5、mAdapter.enable或者mAdapter.disable 580 581 582 583 就先分析enable吧,它会调用对应server端的enable(ture),我们来看看源码 584 585 586 587 public synchronized boolean enable(booleansaveSetting) { 588 589 mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 590 591 "Need BLUETOOTH_ADMIN permission"); 592 593 594 595 // Airplane mode can prevent Bluetoothradio from being turned on. 596 597 //检查是否是飞行模式 598 599 if (mIsAirplaneSensitive &&isAirplaneModeOn() && !mIsAirplaneToggleable) { 600 601 return false; 602 603 } 604 605 //5.1注意与2.3的不同,在2.3中,这里会调用enablethread去调用native的bt_enable,而4.0没有这么做。没事,我们来分析4.0怎么做的。 606 607 mBluetoothState.sendMessage(BluetoothAdapterStateMachine.USER_TURN_ON,saveSetting); 608 609 return true; 610 611 } 612 613 614 615 5.1mBluetoothState.sendMessage 616 617 618 简单理解一下,mBluetoothState是BluetoothAdapterStateMachine类。因此,在分析的之前,简单说一下,它其实就是类似一个状态转换图,根据你所处于的状态,然后再判断收到的操作,进行不同的处理。根据构造函数中的setInitialState(mPowerOff);可以知道初始状态是PowerOff。但是从它给出的状态机可以看出,在PowerOff的状态时,它是通过TURN_HOT/TURN_ON来改变到HotOff状态的,然后才会收到USER_TURN_ON,去该变到BluetootOn的状态。因此,可以肯定的是我们这里的USER_TURN_ON不是它收到的第一个message,因此我们去纠结一下它是从哪里开始改变PowerOff的状态:extra1,然后再来看这里的处理吧:5.2。 620 621 622 623 extra1、mAdapter.enable之前的状态机转变 624 625 626 627 众所周知,android在启动之后会启动一个serverThread的线程,通过这个线程会启动一系列的服务。我们的蓝牙服务也是在这里启动的,android4.0其实在这个地方对状态机进行了修改,我们来看一下源码: 628 629 该代码位于framworks/base/services/java/com/android/server/systemserver.java 630 631 BluetoothServicebluetooth = null; 632 633 BluetoothA2dpServicebluetoothA2dp = null; 634 635 636 637 //模拟器上是不支持Bluetooth的,工厂测试模式也没有Bluetooth(这个不了解) 638 639 // Skip Bluetooth if we have anemulator kernel 640 641 // TODO: Use a more reliable checkto see if this product should 642 643 // support Bluetooth - see bug988521 644 645 if(SystemProperties.get("ro.kernel.qemu").equals("1")) { 646 647 Slog.i(TAG, "No BluetoohService (emulator)"); 648 649 } else if (factoryTest ==SystemServer.FACTORY_TEST_LOW_LEVEL) { 650 651 Slog.i(TAG, "No BluetoothService (factory test)"); 652 653 } else { 654 655 Slog.i(TAG, "BluetoothService"); 656 657 //新建Bluetoothservice,并把他加入到ServiceManager中 658 659 bluetooth = newBluetoothService(context); 660 661 ServiceManager.addService(BluetoothAdapter.BLUETOOTH_SERVICE,bluetooth); 662 663 //extra1.1在启动Bluetooth服务后进行一些初始化,呵呵,这里就对状态机进行了改变 664 665 bluetooth.initAfterRegistration(); 666 667 668 669 //新建了BluetoothA2dpService,并把之加入到了ServiceManager中 670 671 bluetoothA2dp= new BluetoothA2dpService(context, bluetooth); 672 673 ServiceManager.addService(BluetoothA2dpService.BLUETOOTH_A2DP_SERVICE, 674 675 bluetoothA2dp); 676 677 //extra1.2同样的要在之后做些init的工作 678 679 bluetooth.initAfterA2dpRegistration(); 680 681 //得到是否飞行 682 683 int airplaneModeOn =Settings.System.getInt(mContentResolver, 684 685 Settings.System.AIRPLANE_MODE_ON, 0); 686 687 //看Bluetooth是否on,若是打开的状态(没有飞行),则这里会调用enable去打开 688 689 int bluetoothOn =Settings.Secure.getInt(mContentResolver, 690 691 Settings.Secure.BLUETOOTH_ON, 0); 692 693 if (airplaneModeOn == 0&& bluetoothOn != 0) { 694 695 bluetooth.enable(); 696 697 } 698 699 } 700 701 702 703 extra1.1 initAfterRegistration分析 704 705 706 707 public synchronized voidinitAfterRegistration() { 708 709 //得到default的adapter 710 711 mAdapter =BluetoothAdapter.getDefaultAdapter(); 712 713 //创建BluetoothAdapterStateMachine,初始化几个状态,并设初始状态位POWEROFF,这里同时新建了一个EventLoop 714 715 mBluetoothState = newBluetoothAdapterStateMachine(mContext, this, mAdapter); 716 717 mBluetoothState.start(); 718 719 //根据这个xml的bool变量来决定是否先期TURN_HOT,该变量位于frameworks/base/core/res/res/values/config.xml中,默认为true 720 721 if (mContext.getResources().getBoolean 722 723 (com.android.internal.R.bool.config_bluetooth_adapter_quick_switch)) { 724 725 //extra1.2发送TURN_HOT的状态变化message 726 727 mBluetoothState.sendMessage(BluetoothAdapterStateMachine.TURN_HOT); 728 729 } 730 731 //得到对应的EventLoop 732 733 mEventLoop =mBluetoothState.getBluetoothEventLoop(); 734 735 } 736 737 738 739 extra1.2 TURN_HOT message的处理 740 741 742 743 /** 744 745 * Bluetooth module's power is off,firmware is not loaded. 746 747 */ 748 749 private class PowerOff extends State { 750 751 @Override 752 753 public void enter() { 754 755 if (DBG) log("Enter PowerOff:" + getCurrentMessage().what); 756 757 } 758 759 @Override 760 761 public boolean processMessage(Messagemessage) { 762 763 log("PowerOff process message:" + message.what); 764 765 766 767 boolean retValue = HANDLED; 768 769 switch(message.what) { 770 771 …… 772 773 case TURN_HOT: 774 775 //extra1.3这里就是我们寻找了千年的bt_enable所在的地方。我们去看看 776 777 if (prepareBluetooth()) { 778 779 //extra1.5转变状态到warmup,在prepareBluetooth真正完成后,这个状态还会发生改变 780 781 transitionTo(mWarmUp); 782 783 } 784 785 break; 786 787 …… 788 789 790 791 extra1.3prepareBluetooth分析 792 793 794 795 看英文注释就知道了,不解释 796 797 /** 798 799 * Turn on Bluetooth Module, Loadfirmware, and do all the preparation 800 801 * needed to get the Bluetooth Moduleready but keep it not discoverable 802 803 * and not connectable. 804 805 * The last step of this method sets upthe local service record DB. 806 807 * There will be a event reporting thestatus of the SDP setup. 808 809 */ 810 811 private boolean prepareBluetooth() { 812 813 //extra1.4首先还是调用了enableNative的本地方法,到这里你会发现终于和2.3相似了(不过请注意调用的时机不同了,这个在初始化,而2.3在界面的on/off滑动的时候),它还是会调用bt_enable,这个就会调用对应的set_bluetooth_power了 814 815 if(mBluetoothService.enableNative() != 0) { 816 817 return false; 818 819 } 820 821 822 823 // try to start event loop, give 2attempts 824 825 //尝试两次去start event loop 826 827 int retryCount = 2; 828 829 boolean eventLoopStarted = false; 830 831 while ((retryCount-- > 0)&& !eventLoopStarted) { 832 833 mEventLoop.start(); 834 835 // it may take a moment for theother thread to do its 836 837 // thing. Check periodically for a while. 838 839 int pollCount = 5; 840 841 while ((pollCount-- > 0)&& !eventLoopStarted) { 842 843 if(mEventLoop.isEventLoopRunning()) { 844 845 eventLoopStarted =true; 846 847 break; 848 849 } 850 851 try { 852 853 Thread.sleep(100); 854 855 } catch(InterruptedException e) { 856 857 log("prepareBluetooth sleep interrupted: " + pollCount); 858 859 break; 860 861 } 862 863 } 864 865 } 866 867 //出错处理 868 869 if (!eventLoopStarted) { 870 871 mBluetoothService.disableNative(); 872 873 return false; 874 875 } 876 877 878 879 // get BluetoothService ready 880 881 //建立native data以及SDP相关的一些操作,这里将会产生PropertyChanged的UUIDs的signal,对该信号的处理会对状态发生改变,详细分析见extra1.5 882 883 if(!mBluetoothService.prepareBluetooth()) { 884 885 mEventLoop.stop(); 886 887 mBluetoothService.disableNative(); 888 889 return false; 890 891 } 892 893 //设置一个prepare的超时处理,在该时间内没有收到UUID changed的signal将会进行错误处理 894 895 sendMessageDelayed(PREPARE_BLUETOOTH_TIMEOUT,PREPARE_BLUETOOTH_TIMEOUT_TIME); 896 897 return true; 898 899 } 900 901 } 902 903 904 905 extra1.4 bt_enable分析 906 907 908 909 intbt_enable() { 910 911 LOGV(__FUNCTION__); 912 913 914 915 int ret = -1; 916 917 int hci_sock = -1; 918 919 int attempt; 920 921 922 923 //power的设置,on。不解释,可加入对应板子的gpio口的处理,默认就只用了rfkill的处理 924 925 if (set_bluetooth_power(1) < 0) gotoout; 926 927 //开始hciattach服务,这个我们也做了修改,加入了rtk_h5 928 929 LOGI("Starting hciattachdaemon"); 930 931 if (property_set("ctl.start","hciattach") < 0) { 932 933 LOGE("Failed to starthciattach"); 934 935 set_bluetooth_power(0); 936 937 goto out; 938 939 } 940 941 942 943 944 945 // Try for 10 seconds, this can onlysucceed once hciattach has sent the 946 947 // firmware and then turned on hci devicevia HCIUARTSETPROTO ioctl 948 949 for (attempt = 1000; attempt > 0; attempt--) { 950 951 //创建hci_sock 952 953 hci_sock = create_hci_sock(); 954 955 if (hci_sock < 0) goto out; 956 957 //调用ioctl的HCIDEVUP,来判断hciattach是否已经ok了。 958 959 ret = ioctl(hci_sock, HCIDEVUP,HCI_DEV_ID); 960 961 962 963 LOGI("bt_enable: ret: %d, errno:%d", ret, errno); 964 965 if (!ret) { 966 967 break; 968 969 } else if (errno == EALREADY) { 970 971 LOGW("Bluetoothd alreadystarted, unexpectedly!"); 972 973 break; 974 975 } 976 977 978 979 close(hci_sock); 980 981 //等待10 ms后再试一次 982 983 usleep(100000); // 100 ms retry delay 984 985 } 986 987 //10s都没有搞定,需要做个失败的处理 988 989 if (attempt == 0) { 990 991 LOGE("%s: Timeout waiting for HCIdevice to come up, error- %d, ", 992 993 __FUNCTION__, ret); 994 995 if (property_set("ctl.stop","hciattach") < 0) { 996 997 LOGE("Error stoppinghciattach"); 998 999 } 1000 1001 set_bluetooth_power(0); 1002 1003 goto out; 1004 1005 } 1006 1007 //启动bluetoothd服务 1008 1009 LOGI("Starting bluetoothddeamon"); 1010 1011 if (property_set("ctl.start","bluetoothd") < 0) { 1012 1013 LOGE("Failed to startbluetoothd"); 1014 1015 set_bluetooth_power(0); 1016 1017 goto out; 1018 1019 } 1020 1021 1022 1023 ret = 0; 1024 1025 1026 1027 out: 1028 1029 //关闭hci_sock 1030 1031 if (hci_sock >= 0) close(hci_sock); 1032 1033 return ret; 1034 1035 } 1036 1037 1038 1039 extra 1.5 PropetyChanged的UUIDs的处理 1040 1041 1042 1043 event_filter是用来对bluez的dbus的signal进行监听的,有signal产生后,会在这里进行处理。因此,我们直接到这里看看该怎么处理。 1044 1045 1046 1047 //Called by dbus during WaitForAndDispatchEventNative() 1048 1049 staticDBusHandlerResult event_filter(DBusConnection *conn, DBusMessage *msg, 1050 1051 void*data) { 1052 1053 native_data_t *nat; 1054 1055 JNIEnv *env; 1056 1057 DBusError err; 1058 1059 DBusHandlerResult ret; 1060 1061 1062 1063 //err的一个初始化 1064 1065 dbus_error_init(&err); 1066 1067 //得到参数 1068 1069 nat = (native_data_t *)data; 1070 1071 nat->vm->GetEnv((void**)&env,nat->envVer); 1072 1073 if (dbus_message_get_type(msg) !=DBUS_MESSAGE_TYPE_SIGNAL) { 1074 1075 LOGV("%s: not interested (not asignal).", __FUNCTION__); 1076 1077 returnDBUS_HANDLER_RESULT_NOT_YET_HANDLED; 1078 1079 } 1080 1081 1082 1083 LOGV("%s: Received signal %s:%s from%s", __FUNCTION__, 1084 1085 dbus_message_get_interface(msg),dbus_message_get_member(msg), 1086 1087 dbus_message_get_path(msg)); 1088 1089 1090 1091 env->PushLocalFrame(EVENT_LOOP_REFS); 1092 1093 …… 1094 1095 //PropertyChanged这个signal的处理 1096 1097 } else if (dbus_message_is_signal(msg, 1098 1099 "org.bluez.Adapter", 1100 1101 "PropertyChanged")) { 1102 1103 //由msg解析参数 1104 1105 jobjectArray str_array =parse_adapter_property_change(env, msg); 1106 1107 if (str_array != NULL) { 1108 1109 /* Check if bluetoothd has(re)started, if so update the path. */ 1110 1111 jstring property =(jstring)env->GetObjectArrayElement(str_array, 0); 1112 1113 const char *c_property =env->GetStringUTFChars(property, NULL); 1114 1115 //检查Property是否started 1116 1117 if (!strncmp(c_property,"Powered", strlen("Powered"))) { 1118 1119 //若是powered,则看value是否是true,是ture就得到对应的path 1120 1121 jstring value = 1122 1123 (jstring)env->GetObjectArrayElement(str_array, 1); 1124 1125 const char *c_value =env->GetStringUTFChars(value, NULL); 1126 1127 if (!strncmp(c_value,"true", strlen("true"))) 1128 1129 nat->adapter =get_adapter_path(nat->conn); 1130 1131 env->ReleaseStringUTFChars(value, c_value); 1132 1133 } 1134 1135 env->ReleaseStringUTFChars(property, c_property); 1136 1137 //extra1.6调用对应的method_onPropertyChanged函数,该method对应的onPropertyChanged函数 1138 1139 env->CallVoidMethod(nat->me, 1140 1141 method_onPropertyChanged, 1142 1143 str_array); 1144 1145 } elseLOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg); 1146 1147 goto success; 1148 1149 …… 1150 1151 1152 1153 extra1.6 真正的处理函数onPropertyChanged分析 1154 1155 1156 1157 /** 1158 1159 * Called by native code on aPropertyChanged signal from 1160 1161 * org.bluez.Adapter. This method is alsocalled from 1162 1163 * {@link BluetoothAdapterStateMachine} toset the "Pairable" 1164 1165 * property when Bluetooth is enabled. 1166 1167 * 1168 1169 * @param propValues a string arraycontaining the key and one or more 1170 1171 * values. 1172 1173 */ 1174 1175 /*package*/ void onPropertyChanged(String[]propValues) { 1176 1177 BluetoothAdapterPropertiesadapterProperties = 1178 1179 mBluetoothService.getAdapterProperties(); 1180 1181 //先fill up cache 1182 1183 if (adapterProperties.isEmpty()) { 1184 1185 // We have got a property changebefore 1186 1187 // we filled up our cache. 1188 1189 adapterProperties.getAllProperties(); 1190 1191 } 1192 1193 log("Property Changed: " +propValues[0] + " : " + propValues[1]); 1194 1195 String name = propValues[0]; 1196 1197 …… 1198 1199 //对UUIDs的处理 1200 1201 } else if(name.equals("Devices") || name.equals("UUIDs")) { 1202 1203 String value = null; 1204 1205 int len =Integer.valueOf(propValues[1]); 1206 1207 if (len > 0) { 1208 1209 StringBuilder str = newStringBuilder(); 1210 1211 for (int i = 2; i <propValues.length; i++) { 1212 1213 str.append(propValues[i]); 1214 1215 str.append(","); 1216 1217 } 1218 1219 value = str.toString(); 1220 1221 } 1222 1223 //把name和value值加入到property的map中 1224 1225 adapterProperties.setProperty(name,value); 1226 1227 //extra1.7有UUIDs的change signal会刷新Bluetooth的State 1228 1229 if (name.equals("UUIDs")){ 1230 1231 mBluetoothService.updateBluetoothState(value); 1232 1233 } 1234 1235 //对Pairable和Discoverable的处理 1236 1237 } else if(name.equals("Pairable") || name.equals("Discoverable")) { 1238 1239 adapterProperties.setProperty(name,propValues[1]); 1240 1241 1242 1243 if(name.equals("Discoverable")) { 1244 1245 //5.6发送SCAN_MODE_CHANGED的msg,去改变状态机 mBluetoothState.sendMessage(BluetoothAdapterStateMachine.SCAN_MODE_CHANGED); 1246 1247 } 1248 1249 //设置对应的property 1250 1251 String pairable =name.equals("Pairable") ? propValues[1] : 1252 1253 adapterProperties.getProperty("Pairable"); 1254 1255 String discoverable =name.equals("Discoverable") ? propValues[1] : 1256 1257 adapterProperties.getProperty("Discoverable"); 1258 1259 1260 1261 // This shouldn't happen, unlessAdapter Properties are null. 1262 1263 if (pairable == null ||discoverable == null) 1264 1265 return; 1266 1267 1268 1269 int mode =BluetoothService.bluezStringToScanMode( 1270 1271 pairable.equals("true"), 1272 1273 discoverable.equals("true")); 1274 1275 if (mode >= 0) { 1276 1277 //当pairable和discoverable均为true的时候,会发送一个ACTION_SCAN_MODE_CHANGED的广播消息 1278 1279 Intent intent = newIntent(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED); 1280 1281 intent.putExtra(BluetoothAdapter.EXTRA_SCAN_MODE, mode); 1282 1283 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 1284 1285 mContext.sendBroadcast(intent,BLUETOOTH_PERM); 1286 1287 } 1288 1289 } 1290 1291 1292 1293 …… 1294 1295 1296 1297 extra1.7 UUIDs改变带来的State的刷新 1298 1299 1300 /** 1301 1302 * This function is called from BluetoothEvent Loop when onPropertyChanged 1303 1304 * for adapter comes in with UUID property. 1305 1306 * @param uuidsThe uuids of adapter asreported by Bluez. 1307 1308 */ 1309 1310 /*package*/ synchronized voidupdateBluetoothState(String uuids) { 1311 1312 ParcelUuid[] adapterUuids =convertStringToParcelUuid(uuids); 1313 1314 //为什么必须包含所有已经有的uuid??感觉有点反了,再看看 1315 1316 if (mAdapterUuids != null && 1317 1318 BluetoothUuid.containsAllUuids(adapterUuids, mAdapterUuids)) { 1319 1320 //放SERVICE_RECORD_LOADED的信息,此时,处于warm up状态,看extra1.8分析状态如何继续改变 mBluetoothState.sendMessage(BluetoothAdapterStateMachine.SERVICE_RECORD_LOADED); 1321 1322 } 1323 1324 } 1325 1326 1327 1328 extra1.8 UUIDs对状态机改变 1329 1330 1331 /** 1332 1333 * Turning on Bluetooth module's power,loading firmware, starting 1334 1335 * event loop thread to listen on Bluetoothmodule event changes. 1336 1337 */ 1338 1339 private class WarmUp extends State { 1340 1341 1342 @Override 1343 1344 public void enter() { 1345 1346 if (DBG) log("Enter WarmUp:" + getCurrentMessage().what); 1347 1348 } 1349 1350 1351 @Override 1352 1353 public boolean processMessage(Messagemessage) { 1354 1355 log("WarmUp process message:" + message.what); 1356 1357 boolean retValue = HANDLED; 1358 1359 switch(message.what) { 1360 1361 case SERVICE_RECORD_LOADED: 1362 1363 //可以看到,首先会把当时从poweroff过来的一个超时message拿remove了。 1364 1365 removeMessages(PREPARE_BLUETOOTH_TIMEOUT); 1366 1367 //转到hotoff状态,在hotoff状态仍会接收到多个SERVICE_RECORD_LOADED的msg,但是那个状态下该msg将没有任何handled,因此会一直处于hotoff状态 1368 1369 transitionTo(mHotOff); 1370 1371 break; 1372 1373 …… 1374 1375 1376 1377 5.2 mAdapter.enable中mBluetoothState.sendMessage后的状态机处理 1378 1379 1380 1381 由extra的分析可知,此时,Bluetooth的State已经处于HotOff状态了,所以,从这里开始处理State的变换。 1382 1383 1384 1385 /** 1386 1387 * Bluetooth Module has powered, firmwareloaded, event loop started, 1388 1389 * SDP loaded, but the modules staysnon-discoverable and 1390 1391 * non-connectable. 1392 1393 */ 1394 1395 private class HotOff extends State { 1396 1397 @Override 1398 1399 public void enter() { 1400 1401 if (DBG) log("Enter HotOff:" + getCurrentMessage().what); 1402 1403 } 1404 1405 1406 1407 @Override 1408 1409 public boolean processMessage(Messagemessage) { 1410 1411 log("HotOff process message:" + message.what); 1412 1413 1414 1415 boolean retValue = HANDLED; 1416 1417 switch(message.what) { 1418 1419 case USER_TURN_ON: 1420 1421 //发出BluetoothAdapter.STATE_TURNING_ON的广播消息 1422 1423 broadcastState(BluetoothAdapter.STATE_TURNING_ON); 1424 1425 if ((Boolean) message.obj){ 1426 1427 //就是把Settings.Secure.BLUETOOTH_ON设为1。用于标志Bluetooth enable了 1428 1429 persistSwitchSetting(true); 1430 1431 } 1432 1433 // let it fall toTURN_ON_CONTINUE: 1434 1435 //$FALL-THROUGH$ 1436 1437 //注意上面没有break哦 1438 1439 case TURN_ON_CONTINUE: 1440 1441 //这里就是把Bluetooth设为connectable就是Powered=1,这里就把prepareBluetooth中设置的不可连接重新设置回来了。这个重连会产生一些新的变化,它会发送WRITE_SCAN_ENABLE的cmd,因此在该cmd_complete时会有一些新的处理:5.3,它会再次引起状态机的改变:5.6 1442 1443 mBluetoothService.switchConnectable(true); 1444 1445 //进入到Switching状态 1446 1447 transitionTo(mSwitching); 1448 1449 break; 1450 1451 …… 1452 1453 1454 1455 5.3 WRITE_SCAN_ENABLE在cmd_complete后的处理 1456 1457 1458 1459 在bluez中是用cmd_complete函数来监视发出cmd完成后的处理的。该函数具体如下: 1460 1461 1462 1463 static inline void cmd_complete(int index, void *ptr) 1464 1465 { 1466 1467 struct dev_info *dev = &devs[index]; 1468 1469 evt_cmd_complete*evt = ptr; 1470 1471 uint16_topcode = btohs(evt->opcode); 1472 1473 uint8_tstatus = *((uint8_t *) ptr + EVT_CMD_COMPLETE_SIZE); 1474 1475 1476 1477 switch(opcode) { 1478 1479 …… 1480 1481 //WRITE_SCAN_ENABLE命令完成的处理函数,会再发一个READ_SCAN_ENABLE的命令 1482 1483 case cmd_opcode_pack(OGF_HOST_CTL, OCF_WRITE_SCAN_ENABLE): 1484 1485 hci_send_cmd(dev->sk,OGF_HOST_CTL, OCF_READ_SCAN_ENABLE, 1486 1487 0,NULL); 1488 1489 break; 1490 1491 //5.4紧接着就是对READ_SCAN_ENABLE命令完成的处理,它是通过read_scan_complete来实现的 1492 1493 case cmd_opcode_pack(OGF_HOST_CTL, OCF_READ_SCAN_ENABLE): 1494 1495 ptr+= sizeof(evt_cmd_complete); 1496 1497 read_scan_complete(index,status, ptr); 1498 1499 break; 1500 1501 …… 1502 1503 } 1504 1505 1506 1507 5.4 read_scan命令完成的处理 1508 1509 1510 1511 static void read_scan_complete(int index, uint8_t status, void *ptr) 1512 1513 { 1514 1515 struct btd_adapter *adapter; 1516 1517 read_scan_enable_rp*rp = ptr; 1518 1519 1520 1521 DBG("hci%dstatus %u", index, status); 1522 1523 //由index得到对应的adapter 1524 1525 adapter= manager_find_adapter_by_id(index); 1526 1527 if(!adapter) { 1528 1529 error("Unableto find matching adapter"); 1530 1531 return; 1532 1533 } 1534 1535 //5.5这里算是一个通知adapter,mode改变了。 1536 1537 adapter_mode_changed(adapter,rp->enable); 1538 1539 } 1540 1541 1542 1543 5.5 通知adapter,mode发生了改变 1544 1545 1546 void adapter_mode_changed(struct btd_adapter *adapter, uint8_t scan_mode) 1547 1548 { 1549 1550 const gchar *path = adapter_get_path(adapter); 1551 1552 gbooleandiscoverable, pairable; 1553 1554 1555 DBG("old0x%02x new 0x%02x", adapter->scan_mode, scan_mode); 1556 1557 //若相同,则nothing todo 1558 1559 if(adapter->scan_mode == scan_mode){ 1560 1561 #ifdefBOARD_HAVE_BLUETOOTH_BCM 1562 1563 /*we may reset scan_mode already inbtd_adapter_stop(), so comes to here*/ 1564 1565 set_mode_complete(adapter); 1566 1567 #endif 1568 1569 return; 1570 1571 } 1572 1573 //把discoverable的timeout清空 1574 1575 adapter_remove_discov_timeout(adapter); 1576 1577 //这里开始,是设为SCAN_PAGE| SCAN_INQUIRY 1578 1579 switch(scan_mode) { 1580 1581 caseSCAN_DISABLED: 1582 1583 adapter->mode= MODE_OFF; 1584 1585 discoverable= FALSE; 1586 1587 pairable= FALSE; 1588 1589 break; 1590 1591 caseSCAN_PAGE: 1592 1593 adapter->mode= MODE_CONNECTABLE; 1594 1595 discoverable= FALSE; 1596 1597 pairable= adapter->pairable; 1598 1599 break; 1600 1601 case(SCAN_PAGE | SCAN_INQUIRY): 1602 1603 //设一下模式,在有reply要求的情况下,该步骤还是很重要的 1604 1605 adapter->mode= MODE_DISCOVERABLE; 1606 1607 discoverable= TRUE; 1608 1609 pairable= adapter->pairable; 1610 1611 //还要设一个discoverable的时间 1612 1613 if(adapter->discov_timeout != 0) 1614 1615 adapter_set_discov_timeout(adapter, 1616 1617 adapter->discov_timeout); 1618 1619 break; 1620 1621 caseSCAN_INQUIRY: 1622 1623 /*Address the scenario where a low-level application like 1624 1625 * hciconfig changed the scan mode */ 1626 1627 if(adapter->discov_timeout != 0) 1628 1629 adapter_set_discov_timeout(adapter, 1630 1631 adapter->discov_timeout); 1632 1633 1634 1635 /*ignore, this event should not be sent */ 1636 1637 default: 1638 1639 /*ignore, reserved */ 1640 1641 return; 1642 1643 } 1644 1645 1646 1647 /*If page scanning gets toggled emit the Pairable property */ 1648 1649 //这里会发一个property_changed的pairable的signal 1650 1651 if((adapter->scan_mode & SCAN_PAGE) != (scan_mode & SCAN_PAGE)) 1652 1653 emit_property_changed(connection,adapter->path, 1654 1655 ADAPTER_INTERFACE,"Pairable", 1656 1657 DBUS_TYPE_BOOLEAN,&pairable); 1658 1659 1660 1661 if(!discoverable) 1662 1663 adapter_set_limited_discoverable(adapter,FALSE); 1664 1665 //这里会发一个property_changed的discoverable的signal 1666 1667 emit_property_changed(connection,path, 1668 1669 ADAPTER_INTERFACE,"Discoverable", 1670 1671 DBUS_TYPE_BOOLEAN,&discoverable); 1672 1673 adapter->scan_mode= scan_mode; 1674 1675 1676 1677 set_mode_complete(adapter); 1678 1679 }
至此,蓝牙的使能主要过程已经全部搞定。
原文地址:http://blog.csdn.net/xdyang1987/article/details/7771388