Android Bluetooth Analysis

Source: Internet
Author: User
Tags usleep

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();                }               } 

First, Ro. kernel. qemu determines whether the simulator is started. If not, start the Bluetooth service; otherwise, skip it. If mongothon is not 0, Bluetooth. Enable () is enabled by default.
Follow in to see the operations of Bluetooth. Enable (), in javasthservice. 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;    }

First, judge the permission and flight mode, and finally send the message user_turn_on, indicating that the Bluetooth mblustmthstate is a state machine to be enabled, so it enters bluetoothadapterstatemachine. java.

The status is in the poweroff state during initialization, so it enters the 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;                .....................................             }   

As you can see, after the Bluetooth state machine receives user_turn_on, it first broadcasts that the Bluetooth adapter is in the state_turning_on status. There are four statuses:

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

Next, let's look at the preparebluetooth () function:

        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;            }            .............................         } 

Mblustmthservice. enablenative () calls the enablenative method of javasthservice, that is, the JNI method. Therefore, it enters android_server_gatethservice.cpp:

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

Bt_enable calls the system/Bluetooth/bluedroid/Bluetooth. C function:

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;}

Here, set_effecth_power reads the hardware status of the bluetooth device. If it is on, the bluetooth device is enabled. How can this problem be solved? That is, when the Bluetooth HCI driver is registered, it registers an rfkill and presents it to the upper layer in the form of a device node, which indicates the power status, for example, we may see a button on the computer keyboard to switch Bluetooth or WiFi. This key value will be read here. If it is 1, you can enable Bluetooth. Otherwise, you cannot use Bluetooth. We do not have such a key value here, so we will block it.

Next, property_set ("CTL. Start", "hciattach") starts the HCI service, and then create_hci_sock creates a socket to communicate with the HCI service.

Next ioctl, the parameter is hcidevup, it enters the drive 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);    .....................................}

Call hci_dev_open (ARG). The effect of this function is like using the Bluetooth debugging tool hciconfig under the terminal.

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;    }    .....................................}

Here we get an hci_dev device and then call its open function. In fact, the callback function when we register the Bluetooth driver will call the OPEN function of our Bluetooth driver.

The main function of mblustmthservice in the enablenative () function is to enable the bluetooth device through a series of code. If the device driver code is correct, the value returned by enablenative () is true. When debugging a bluetooth device, you can run the following command (hciconfig) on a Linux or android terminal:

# Hciconfig-A if the driver can be bound to the device, we will see some important information about the bluetooth device, such as the physical address, bus type, and protocol type of the bluetooth device.
Return to the preparebluetooth function of the Bluetooth state machine, and then execute meventloop. Start (). Therefore, go to javastheventloop. Java:

    /* package */ void start() {                                                                                                                                       if (!isEventLoopRunningNative()) {            if (DBG) log("Starting Event Loop thread");            startEventLoopNative();        }        } 

Starteventloopnative is the JNI method:

The function here is very long. It is mainly used to create a socket, create a thread dedicated to reading data, Mount bluz on the slave, and read data in the last round-robin mode, if there is data, process it based on the data type.

After analyzing the preparebluetooth, if there is no problem, use persistswitchsetting to write the status settings. Secure. gateth_on to the database and save it.

The state machine is in the front transitionto (mwarmup), has switched to the mwarmup mode, and sent the defermessage (obtainmessage (turn_on_continue), so it enters the warmup state:

Not complete, refer to http://www.cnblogs.com/chenbin7/archive/2012/09/05/2670652.html

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

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.