android bluetooth分析

來源:互聯網
上載者:User

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

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.