adroid 蓝牙前段控制
内容简介:本文详细分析了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 }