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