首页 > 代码库 > Android4.0蓝牙使能的详细解析

Android4.0蓝牙使能的详细解析

内容简介:本文详细分析了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));

于是,我们得以进入真正的蓝牙操作的殿堂,好好进去看看吧。

代码来源:http://code.metager.de/source/xref/android/

复制代码
   
   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 = http://www.mamicode.com/HANDLED;> 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 =
http://www.mamicode.com/1122   "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 = http://www.mamicode.com/null;",");
1216   
1217                   }
1218   
1219                   value = http://www.mamicode.com/str.toString();"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 = http://www.mamicode.com/HANDLED;>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 = http://www.mamicode.com/HANDLED;>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   }
复制代码

 

至此,蓝牙的使能主要过程已经全部搞定。