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