Android启动之bluetooth

来源:互联网 发布:网络促销方案例文 编辑:程序博客网 时间:2024/04/30 15:51

前一段时间我们分析了kernelbluetooth的初始化操作,从这一章起,晓东将会和大家一起正式进入到Androidbluetooth的分析。毫无疑问,我们依然需要知道在Android启动的时候,蓝牙究竟有做些什么。

         首先我们来回顾一下Android启动的一般流程,有人把它归结为4个步骤,分别为1init进程启动;2Native服务启动;3System serverAndroid服务启动;4Home启动。那么,我们来一个个看在这几个步骤中,都有哪些是和蓝牙有关的。

1init中的bluetooth

 

[html] view plaincopy
  1. #首先是创建了两个文件夹和bluetooth相关  
  2.     mkdir /data/misc/bluetoothd 0770 bluetooth bluetooth  
  3. mkdir /data/misc/bluetooth 0770 system system  
  4. #新建了一个dbus的service,dbus是用于bluez和jni层交互的  
  5. #细心的同学已经发了,他是没有disabled的,所以,会直接启动哦  
  6. #不过dbus只是一个通路而已,我们暂时并不准备去详细地分析  
  7. service dbus /system/bin/dbus-daemon --system --nofork  
  8.     class main  
  9.     socket dbus stream 660 bluetooth bluetooth  
  10.     user bluetooth  
  11.     group bluetooth net_bt_admin  
  12. #新建了bluetoothd的service,这个就是bluez了  
  13. service bluetoothd /system/bin/bluetoothd -n  
  14.     class main  
  15.     socket bluetooth stream 660 bluetooth bluetooth  
  16.     socket dbus_bluetooth stream 660 bluetooth bluetooth  
  17.     # init.rc does not yet support applying capabilities, so run as root and  
  18.     # let bluetoothd drop uid to bluetooth with the right linux capabilities  
  19.     group bluetooth net_bt_admin misc  
  20.     disabled  
  21. #这里就是各个文件的权限配置了  
  22.     chmod 666 /dev/ttyS0  
  23.     chmod 666 /proc/bluetooth/sleep/proto  
  24.     chmod 666 /sys/class/rfkill/rfkill0/state  
  25.     chmod 666 /sys/class/rfkill/rfkill0/type  
  26.     chown bluetooth bluetooth /sys/class/rfkill/rfkill0/state  
  27.     chown bluetooth bluetooth /sys/class/rfkill/rfkill0/type  
  28. #一个hciattach的service,hciattach是bluetooth的一个工具,这里可以用来启动蓝牙  
  29. #涉及到一些vendor的信息后面就写成***了  
  30. service hciattach /system/bin/logwrapper /system/bin/hciattach -n /dev/ttyS0 ***  
  31.     class main  
  32.     user bluetooth  
  33.     group bluetooth net_bt_admin  
  34.     disabled  
  35.     oneshot  

总得来说,init的过程和蓝牙相关的就是启动了dbus service,然后新建了bluetoothdhciattachservice,其它就只有一些文件和文件夹以及他们权限相关的内容修改了。

Native服务启动就和蓝牙没有什么大的关系了,我们直接去看system server中的Android服务启动了

2system server中的bluetooth

         system server会启动ServerThread,至于为什么会走到这里,应该会有无数的文章详细介绍这个吧,晓东就不献丑了。我们直接来看蓝牙相关的内容:(代码位于framework/base/services/java/com/android/server/systemserver.java

[cpp] view plaincopy
  1. class ServerThread extends Thread {  
  2.     ……  
  3.     @Override  
  4. public void run() {  
  5.   
  6. ……  
  7.             // Skip Bluetooth if we have an emulator kernel  
  8.             // TODO: Use a more reliable check to see if this product should  
  9.             // support Bluetooth - see bug 988521  
  10.             //若是模拟器,就不用bluetooth了  
  11.             if (SystemProperties.get("ro.kernel.qemu").equals("1")) {  
  12.                 Slog.i(TAG, "No Bluetooh Service (emulator)");  
  13.                 //low level的工厂测试模式,也不启动bluetooth  
  14.             } else if (factoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {  
  15.                 Slog.i(TAG, "No Bluetooth Service (factory test)");  
  16.             } else {  
  17. //上面两种都是非正常的启动,我们可以忽略  
  18.                 Slog.i(TAG, "Bluetooth Service");  
  19.                 //新建bluetoothservice,详细见2.1  
  20.                 //加入到servicemanager中,是BluetoothAdapter.BLUETOOTH_SERVICE  
  21.                 bluetooth = new BluetoothService(context);  
  22.                 ServiceManager.addService(BluetoothAdapter.BLUETOOTH_SERVICE, bluetooth);  
  23.                 //注册之后的init,详细见2.2  
  24.                 bluetooth.initAfterRegistration();  
  25.                 //新建a2dpservice,并同样加入到servicemanager中,详细见2.3  
  26.                 bluetoothA2dp = new BluetoothA2dpService(context, bluetooth);  
  27.                 ServiceManager.addService(BluetoothA2dpService.BLUETOOTH_A2DP_SERVICE,  
  28.                                           bluetoothA2dp);  
  29.                 //a2dp的init  
  30.                 bluetooth.initAfterA2dpRegistration();  
  31.                 //得到是否是飞行模式  
  32.                 int airplaneModeOn = Settings.System.getInt(mContentResolver,  
  33.                         Settings.System.AIRPLANE_MODE_ON, 0);  
  34.                 //看bluetooth在上次关闭的时候是否on的  
  35.                 int bluetoothOn = Settings.Secure.getInt(mContentResolver,  
  36.                     Settings.Secure.BLUETOOTH_ON, 0);  
  37.                     //若是非飞行模式,上次关闭前是打开,则使能bt  
  38.                     //使能bt的过程这篇文章就不介绍了,后面会另开一篇介绍  
  39.                 if (airplaneModeOn == 0 && bluetoothOn != 0) {  
  40.                     bluetooth.enable();  
  41.                 }  
  42.             }  

2.1 bluetoothservice的构造

bluetoothservice可以说是bluetooth的一个核心组成了,很多初始化都是由它这里发起的,我们来详细阅读一下:(代码位于/framework/base/core/java/android/server/bluetoothservice.java

[cpp] view plaincopy
  1.   public BluetoothService(Context context) {  
  2.         mContext = context;  
  3.   
  4.         // Need to do this in place of:  
  5.         // mBatteryStats = BatteryStatsService.getService();  
  6.         // Since we can not import BatteryStatsService from here. This class really needs to be  
  7.         // moved to java/services/com/android/server/  
  8.         //得到battery的状态  
  9.         mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService("batteryinfo"));  
  10.         //是否是bt wifi 共存  
  11.         if (SystemProperties.get("ro.btwifi.coexist""true").equals("false")) {  
  12.             supportBtWifiCoexit = false;  
  13.         }  
  14.             //jni层的nativedata的一些初始化。最主要的是检查一下dbus是否能够用  
  15.             //这里就不详细介绍了,很简单,代码位于frameworks/base/core/jni/android_server_bluetoothservice.cpp中  
  16.         initializeNativeDataNative();  
  17.             //检查bt是否已经enable了,理论是不应该enable的  
  18.         if (isEnabledNative() == 1) {  
  19.             Log.w(TAG, "Bluetooth daemons already running - runtime restart? ");  
  20.             disableNative();  
  21.         }  
  22.             //这个是用来表示配对的一些状态的  
  23.             //主要是注册一个BluetoothDevice.ACTION_PAIRING_REQUEST的receiver,这样在有pair的请求的时候,他会把pair的device加入到mPairingRequestRcvd列表中  
  24.         mBondState = new BluetoothBondState(context, this);  
  25. //主要就是建了一个mPropertiesMap的hash表,保存adapter的properties        mAdapterProperties = new BluetoothAdapterProperties(context, this);  
  26. //新建了一个mPropertiesMap的hash表,用来保存device的properties  
  27.         mDeviceProperties = new BluetoothDeviceProperties(this);  
  28.   
  29.        //新建一个deviceservice channel的hash表,还有别的hash表的建立,等用到的时候再一一详细介绍  
  30. mDeviceServiceChannelCache = new HashMap<String, Map<ParcelUuid, Integer>>();  
  31.         mDeviceOobData = new HashMap<String, Pair<byte[], byte[]>>();  
  32.         mUuidIntentTracker = new ArrayList<String>();  
  33.         mUuidCallbackTracker = new HashMap<RemoteService, IBluetoothCallback>();  
  34.         mServiceRecordToPid = new HashMap<Integer, ServiceRecordClient>();  
  35.         mDeviceProfileState = new HashMap<String, BluetoothDeviceProfileState>();  
  36. //初始化两个profiles的状态机。BluetoothProfileState是用来统一管理profile的状态的,这里注册了A2DP和HFP两个profile  
  37.         mA2dpProfileState = new BluetoothProfileState(mContext, BluetoothProfileState.A2DP);  
  38.         mHfpProfileState = new BluetoothProfileState(mContext, BluetoothProfileState.HFP);  
  39.             //启动这两个状态机,开始接收各种message  
  40.         mHfpProfileState.start();  
  41.         mA2dpProfileState.start();  
  42.   
  43.         mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);  
  44.         Intent intent = new Intent(DISCOVERABLE_ALARM);  
  45.         mPendingIntent = PendingIntent.getBroadcast(mContext, 0, intent, 0);  
  46.   
  47.         IntentFilter filter = new IntentFilter();  
  48. //就是监听ACTION_AIRPLANE_MODE_CHANGED  
  49.         registerForAirplaneMode(filter);  
  50. //加入DISCOVERABLE_ALARM,ACTION_DOCK_EVENT,ACTION_BOOT_COMPLETED的监听  
  51.         filter.addAction(DISCOVERABLE_ALARM);  
  52.         filter.addAction(Intent.ACTION_DOCK_EVENT);  
  53. //这里说明一下ACTION_BOOT_COMPLETED的处理,就是置一个mBootCompleted = true;所以,就不另外特别说明了  
  54.         filter.addAction(Intent.ACTION_BOOT_COMPLETED);  
  55.         mContext.registerReceiver(mReceiver, filter);  
  56. //构造几个profile的处理,有hid,pan和health,没有什么好说的  
  57.         mBluetoothInputProfileHandler = BluetoothInputProfileHandler.getInstance(mContext, this);  
  58.         mBluetoothPanProfileHandler = BluetoothPanProfileHandler.getInstance(mContext, this);  
  59.         mBluetoothHealthProfileHandler = BluetoothHealthProfileHandler.getInstance(mContext, this);  
  60. //再新建两个hash表  
  61.         mIncomingConnections = new HashMap<String, Pair<Integer, String>>();  
  62.         mProfileConnectionState = new HashMap<Integer, Pair<Integer, Integer>>();  
  63. }  

2.2initAfterRegistration

这个函数是用来在注册之后进行初始化的,所以,可以说是bluetoothservice中被调用的第一个函数了,我们来看看它做了一些什么:

[cpp] view plaincopy
  1. public synchronized void initAfterRegistration() {  
  2. /新建了一个bluetoothadapter,这很重要,adapter和bluetoothservice是绑定的,后期上层ui都是同adapter那边来找到bluetoothservice的  
  3.        mAdapter = BluetoothAdapter.getDefaultAdapter();  
  4. /新建bluetoothadapter的状态机,后面我会另外开一篇文章来详细介绍状态机  
  5.        mBluetoothState = new BluetoothAdapterStateMachine(mContext, this, mAdapter);  
  6.         //start状态机  
  7.        mBluetoothState.start();  
  8.         //看是否支持qucik switch,若是支持,我们会在开机的时候就默认为hot状态  
  9.         //这里就是4.0和2.3中最大的不同,就是其实默认支持quick switch的情况下,蓝牙是打开的,只是没有显示在ui界面上而已。关于这里,我会另开一篇文章来介绍  
  10.        if (mContext.getResources().getBoolean  
  11.            (com.android.internal.R.bool.config_bluetooth_adapter_quick_switch)) {  
  12.            mBluetoothState.sendMessage(BluetoothAdapterStateMachine.TURN_HOT);  
  13.        }  
  14.         //得到bluetooth的eventloop,eventloop在adapterstatemachine构造的时候创建的,这个很重要,不过我们也放到另外一篇文章中去详细介绍  
  15.        mEventLoop = mBluetoothState.getBluetoothEventLoop();  
  16.    }  

2.3 BluetoothA2dpService

这个是a2dp service的构造

[cpp] view plaincopy
  1.  public BluetoothA2dpService(Context context, BluetoothService bluetoothService) {  
  2.        mContext = context;  
  3. //得到audioservice  
  4.        mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);  
  5. //和bluetoothservice关联  
  6.        mBluetoothService = bluetoothService;  
  7.        if (mBluetoothService == null) {  
  8.            throw new RuntimeException("Platform does not support Bluetooth");  
  9.        }  
  10. /和bluetoothservice类似,就是初始化native的data和检查dbus  
  11.        if (!initNative()) {  
  12.            throw new RuntimeException("Could not init BluetoothA2dpService");  
  13.        }  
  14.   
  15.        mAdapter = BluetoothAdapter.getDefaultAdapter();  
  16. //几个action的处理  
  17.        mIntentFilter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);  
  18.        mIntentFilter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);  
  19.        mIntentFilter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);  
  20.        mIntentFilter.addAction(AudioManager.VOLUME_CHANGED_ACTION);  
  21.        mContext.registerReceiver(mReceiver, mIntentFilter);  
  22.   
  23.        mAudioDevices = new HashMap<BluetoothDevice, Integer>();  
  24. /看bluetooth是否on  
  25.        if (mBluetoothService.isEnabled())  
  26.            onBluetoothEnable();  
  27.        mTargetA2dpState = -1;  
  28. /使得bluetoothservice那边能找到a2dpservice  
  29.        mBluetoothService.setA2dpService(this);  
  30.    }  

至此,android启动时,bluetooth的一些操作就已经都比较明了了。在init过程中:“init的过程和蓝牙相关的就是启动了dbus service,然后新建了bluetoothdhciattachservice,其它就只有一些文件和文件夹以及他们权限相关的内容修改了。”

system service过程中,启动了bluetooth servicea2dp service。这之中比较重要的是构造了bluetoothadapater的状态机,这个是后期蓝牙各种状态变化的基础,同时启动了eventloop用于处理从dbus过来的各种event,这两者晓东会另开篇幅和大家详细介绍。

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 穿越火线与主机连接不稳定怎么办 word被锁定无法编辑怎么办 平衡车系统乱了怎么办 监控老是滴滴的响怎么办 磁盘已满 文件未保存怎么办 cocos只有代码没有项目怎么办 电脑系统管理员密码忘记了怎么办 魔兽小队不显示职业颜色怎么办 魔兽多余的橙装怎么办? f117-f6不读硬盘怎么办 中飞院飞行学生停飞了怎么办 军人对你敬礼时怎么办 小孩抱着就睡放下就醒怎么办 着火了怎么办 我的世界 生存战争2感冒了怎么办 生存战争2吐了怎么办 我的世界hqm重置怎么办 不小心打了110怎么办 我的世界皮肤有黑影怎么办 我的世界字体变大了怎么办 生锈的铁钉扎了怎么办 每天晚上窗纱上老有蝙蝠倒挂怎么办 我的世界没有痒怎么办 七日杀被ban了怎么办 吕框箱子上保护摸撕不掉怎么办 我的世界开光影卡怎么办 我的世界买不了怎么办 我的世界延迟高怎么办 我的世界过于昂贵怎么办 白色麻布染上别的颜色怎么办 印度老山檀香开裂了怎么办 专升本没过线怎么办 西安公租房小孩上学怎么办 全民k歌直播没人怎么办 在全民直播没人看怎么办 皮肤又黄又粗怎么办 被强制消费后应怎么办? 当保安不发工资怎么办? 辅警改革流管员怎么办 退伍证上照片毁了怎么办 辅警年龄大了怎么办