android bluetooth分析

allwinner4.0.4:

SystemServer.java:

            if (SystemProperties.get("ro.kernel.qemu").equals("1") ||
                SystemProperties.get("ro.bluetooth.disable").equals("1")) {
                Slog.i(TAG, "No Bluetooh Service (emulator)");
            } else if (factoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
                Slog.i(TAG, "No Bluetooth Service (factory test)");
            } else {
                Slog.i(TAG, "Bluetooth Service");
                bluetooth = new BluetoothService(context);
                ServiceManager.addService(BluetoothAdapter.BLUETOOTH_SERVICE, bluetooth);
                bluetooth.initAfterRegistration();
                bluetoothA2dp = new BluetoothA2dpService(context, bluetooth);
                ServiceManager.addService(BluetoothA2dpService.BLUETOOTH_A2DP_SERVICE,
                                          bluetoothA2dp);
                bluetooth.initAfterA2dpRegistration();

                int airplaneModeOn = Settings.System.getInt(mContentResolver,
                        Settings.System.AIRPLANE_MODE_ON, 0); 
                int bluetoothOn = Settings.Secure.getInt(mContentResolver,
                    Settings.Secure.BLUETOOTH_ON, 0); 
                if (airplaneModeOn == 0 && bluetoothOn != 0) {
                    bluetooth.enable();
                }   
            } 

首先ro.kernel.qemu判断是不是模拟器启动,如果不是,采取启动蓝牙服务,否则略过;接着如果bluetoothOn不为0,则bluetooth.enable()开机默认打开蓝牙
跟进去看看bluetooth.enable()的操作,在BluetoothService.java中:

    public synchronized boolean enable(boolean saveSetting) {
        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
                                                "Need BLUETOOTH_ADMIN permission");
                                                                                                                                                               
        // Airplane mode can prevent Bluetooth radio from being turned on.
        if (mIsAirplaneSensitive && isAirplaneModeOn() && !mIsAirplaneToggleable) {
            return false;
        }    
        mBluetoothState.sendMessage(BluetoothAdapterStateMachine.USER_TURN_ON, saveSetting);
        return true;
    }

先判断权限和飞行模式,最后发送消息USER_TURN_ON,表示要打开蓝牙了mBluetoothState是一个状态机,所以进入BluetoothAdapterStateMachine.java中。

初始化时候状态是在PowerOff,所以进入PowerOff中:

    private class PowerOff extends State {
        @Override
        public void enter() {
            if (DBG) log("Enter PowerOff: " + getCurrentMessage().what);
        }
        @Override
        public boolean processMessage(Message message) {
            log("PowerOff process message: " + message.what);

            boolean retValue = HANDLED;
            switch(message.what) {
                case USER_TURN_ON:
                    // starts turning on BT module, broadcast this out
                    broadcastState(BluetoothAdapter.STATE_TURNING_ON);
                    transitionTo(mWarmUp);
                    if (prepareBluetooth()) {
                        // this is user request, save the setting
                        if ((Boolean) message.obj) {
                            persistSwitchSetting(true);
                        }
                        // We will continue turn the BT on all the way to the BluetoothOn state
                        deferMessage(obtainMessage(TURN_ON_CONTINUE));
                    } else {
                        Log.e(TAG, "failed to prepare bluetooth, abort turning on");
                        transitionTo(mPowerOff);
                        broadcastState(BluetoothAdapter.STATE_OFF);
                    }
                    break;
                ..................................... 
            }   

可以看到,蓝牙状态机接收到USER_TURN_ON后,首先广播蓝牙适配器处于STATE_TURNING_ON状态,蓝牙适配器状态有四种:

state_off(10),state_turning_on(11),state_on(12),state_turning_off(14)

接下来看prepareBluetooth()函数:

        private boolean prepareBluetooth() {
            if (mBluetoothService.enableNative() != 0) {
                return false;
            }

            // try to start event loop, give 2 attempts
            int retryCount = 2;
            boolean eventLoopStarted = false;
            while ((retryCount-- > 0) && !eventLoopStarted) {
                mEventLoop.start();
                // it may take a moment for the other thread to do its
                // thing.  Check periodically for a while.
                int pollCount = 5;
                while ((pollCount-- > 0) && !eventLoopStarted) {
                    if (mEventLoop.isEventLoopRunning()) {
                        eventLoopStarted = true;
                        break;
                    }                                                                                                                                          
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        log("prepareBluetooth sleep interrupted: " + pollCount);
                        break;
                    }   
                }   
            }   

            if (!eventLoopStarted) {
                mBluetoothService.disableNative();
                return false;
            }
            .............................
         } 

mBluetoothService.enableNative()调用了BluetoothService的enableNative,也就是JNI方法了,所以进入android_server_BluetoothService.cpp中:

static jint enableNative(JNIEnv *env, jobject object) {
#ifdef HAVE_BLUETOOTH
    LOGV("%s", __FUNCTION__);
    return bt_enable();                                                                                                                                        
#endif
    return -1;
}

bt_enable调用的是system/bluetooth/bluedroid/bluetooth.c的函数:

int bt_enable() {
    LOGV(__FUNCTION__);

    int ret = -1; 
    int hci_sock = -1; 
    int attempt;
    
    LOGI("bt_enable()");
#ifndef BOARD_HAVE_BLUETOOTH_CSR
    //if (set_bluetooth_power(1) < 0) goto out;                                                                                                                
#else
    LOGI("Starting bccmd command");
    if (property_set("ctl.start", "bccmd") < 0) {
        LOGE("Fail to bccmd");
        goto out;
    }   
    sleep(5);
#endif

#if defined(SW_BOARD_HAVE_BLUETOOTH_RTK)
    usleep(1000000);  // 1 seconds
#endif

    LOGI("Starting hciattach daemon");
    if (property_set("ctl.start", "hciattach") < 0) {
        LOGE("Failed to start hciattach");
#ifndef BOARD_HAVE_BLUETOOTH_CSR
        //set_bluetooth_power(0);
#endif
        goto out;
    } 
    // Try for 10 seconds, this can only succeed once hciattach has sent the
    // firmware and then turned on hci device via HCIUARTSETPROTO ioctl
    for (attempt = 1000; attempt > 0;  attempt--) {
        hci_sock = create_hci_sock();
        if (hci_sock < 0) goto out;

        ret = ioctl(hci_sock, HCIDEVUP, HCI_DEV_ID);

        LOGI("bt_enable: ret: %d, errno: %d", ret, errno);
        if (!ret) {
            break;
        } else if (errno == EALREADY) {
            LOGW("Bluetoothd already started, unexpectedly!");
            break;
        }

        close(hci_sock);
        usleep(100000);  // 100 ms retry delay
    }                                                                                                                                                          
    if (attempt == 0) {
        LOGE("%s: Timeout waiting for HCI device to come up, error- %d, ",
            __FUNCTION__, ret);
        if (property_set("ctl.stop", "hciattach") < 0) {
            LOGE("Error stopping hciattach");
        }
#ifndef BOARD_HAVE_BLUETOOTH_CSR
        //set_bluetooth_power(0);
#endif
        goto out;
    }
    LOGI("Starting bluetoothd deamon");
    if (property_set("ctl.start", "bluetoothd") < 0) {
        LOGE("Failed to start bluetoothd");
#ifndef BOARD_HAVE_BLUETOOTH_CSR
        //set_bluetooth_power(0);
#endif
        goto out;
    }

#ifdef BOARD_HAVE_BLUETOOTH_CSR
    if (property_set("ctl.start", BTFILTER_NAME) < 0) {
        LOGE("Failed to start abtfilt");
        goto out;
    }
    usleep(1000);
#endif

    ret = 0;

out:
    if (hci_sock >= 0) close(hci_sock);
    return ret;
}

这里set_bluetooth_power会读取蓝牙的硬件状态,如果为on的话才开启蓝牙,怎么说呢?也就是蓝牙的HCI驱动注册的时候会注册一个rfkill,以一个设备节点的形式呈现给上层,它指示着电源的状态,比如我们在电脑键盘上面可能会看见一个按键来开关蓝牙或者wifi之类的。这里会去读这个键值,如果是1代表可以开启蓝牙的,否则是没法使用蓝牙的。我们这里没有这样的键值,所以将它屏蔽掉。

接着property_set("ctl.start", "hciattach")启动HCI服务,然后create_hci_sock来创建socket,这样就可以和HCI服务通讯了

接下来ioctl,参数是HCIDEVUP,就进入了驱动linux-3.0/net/bluetooth/hci_sock.c中:

static int hci_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
{
   .................................
    case HCIDEVUP:
        if (!capable(CAP_NET_ADMIN))
            return -EACCES;
        return hci_dev_open(arg);
    .....................................
}
调用hci_dev_open(arg), 这个函数的效果就好比我们在终端下面使用蓝牙调试工具hciconfig
int hci_dev_open(__u16 dev)                                                                                                                                    
{       
    struct hci_dev *hdev;
    int ret = 0;
        
    hdev = hci_dev_get(dev);
    if (!hdev)
        return -ENODEV;
    .............................
    if (hdev->open(hdev)) {
        ret = -EIO;
        goto done;
    }
    .....................................
}
这里得到一个hci_dev设备,然后调用他的open,其实就是我们注册蓝牙驱动时候的回调函数,会调用我们蓝牙驱动的open

mBluetoothService在enableNative()函数主要功能就是通过一系列代码来打开蓝牙设备。如果设备驱动代码没有问题的话,我们enableNative()返回的将会是true。在实际调试蓝牙设备时候,我们可以通过在linux或者android的终端下面使用自带的工具命令(hciconfig),执行:

# hciconfig –a如果驱动能够和设备绑定的话,我们就会看到蓝牙设备的一些比较重要信息,如:蓝牙的物理地址,总线类型,协议类型等
回到蓝牙状态机的prepareBluetooth函数中,接着执行mEventLoop.start(),所以进入BluetoothEventLoop.java中:

    /* package */ void start() {                                                                                                                               

        if (!isEventLoopRunningNative()) {
            if (DBG) log("Starting Event Loop thread");
            startEventLoopNative();
        }    
    } 

startEventLoopNative是JNI方法:

这里的函数很长,主要是创建socket,创建一个专门读取数据的线程,将bluz挂在dbus上,最后一轮询的方式读取数据,有数据来了的话根据数据的类型做相应的处理

分析完prepareBluetooth,如果没有问题,就用persistSwitchSetting将状态Settings.Secure.BLUETOOTH_ON写到数据库中保存起来

状态机在前面transitionTo(mWarmUp),已经切换到了mWarmUp模式,并且发送了deferMessage(obtainMessage(TURN_ON_CONTINUE)),所以进入WarmUp状态:


未完,参考http://www.cnblogs.com/chenbin7/archive/2012/09/05/2670652.html



你可能感兴趣的:(android bluetooth分析)