展会信息港展会大全

[Android源码分析]蓝牙打开分析--苦尽甘来之再次回到jni之上
来源:互联网   发布日期:2015-09-28 16:00:35   浏览:1817次  

导读:第三章,苦尽甘来之再次回到jni之上 经过了上面两章的分析,我们基本已经对一次的“下乡活动”了解清楚了,下面我们就要详细分析再次回到jni之上的一些操作了。再这之前,我们...

第三章,苦尽甘来之再次回到jni之上

经过了上面两章的分析,我们基本已经对一次的“下乡活动”了解清楚了,下面我们就要详细分析再次回到jni之上的一些操作了。再这之前,我们先来看看这次下乡活动从乡下都带来了什么?

其实很少蛮清晰的,就是带回来了几个property change的event,他们分别是UUIDs,pairable=false,powered=false,class, discoverable=false。我们来看一下,他们对上层都有哪些影响。

eventloop中对property change的处理函数是:

/*package*/ void onPropertyChanged(String[] propValues) {

所以,我们要分析各个propertychange的影响分析这个函数就可以了。下面,我们来具体分析这些property change的影响:

1、UUIDs的处理

[cpp]

} else if (name.equals("Devices") || name.equals("UUIDs")) {

String value = null;

int len = Integer.valueOf(propValues[1]);

if (len > 0) {

StringBuilder str = new StringBuilder();

for (int i = 2; i < propValues.length; i++) {

str.append(propValues[i]);

str.append(",");

}

value = str.toString();

}

//加入到property中,把UUIDs和对应的value保存

adapterProperties.setProperty(name, value);

if (name.equals("UUIDs")) {

//若是uuid,这个函数是很重要的

mBluetoothService.updateBluetoothState(value);

}

1.2 mBluetoothService.updateBluetoothState(value)函数分析

[cpp]

/*package*/ synchronized void updateBluetoothState(String uuids) {

ParcelUuid[] adapterUuids = convertStringToParcelUuid(uuids);

//当uuid都被注册成功之后,就可以发送SERVICE_RECORD_LOADED的msg了

if (mAdapterUuids != null &&

BluetoothUuid.containsAllUuids(adapterUuids, mAdapterUuids)) {

mBluetoothState.sendMessage(BluetoothAdapterStateMachine.SERVICE_RECORD_LOADED);

}

}

所以,UUIDs的property change的最终目的就是发送SERVICE_RECORD_LOADED的msg,这个msg是从warmup到hotoff的关键条件,这个我们在蓝牙的状态机里面有详细分析,不过,我们不妨在这里也再次分析一下:

[cpp]

switch(message.what) {

case SERVICE_RECORD_LOADED:

removeMessages(PREPARE_BLUETOOTH_TIMEOUT);

//转换到hotoff的状态

transitionTo(mHotOff);

break;

到了hotoff状态之后,我们需要继续处理在poweroff状态中传入的turnon continue的msg:

case TURN_ON_CONTINUE:

//这个就是设置powered为true

mBluetoothService.switchConnectable(true);

transitionTo(mSwitching);

break;

//从注释来看,这里是用来设置connectable和pairable的,又要到jni层之下,不过我们直接去看吧,就没有必要再分开分析了。

/*package*/ synchronized void switchConnectable(boolean on) {

setAdapterPropertyBooleanNative("Powered", on ? 1 : 0);

1.3 bluez中set property的powered的处理

这个函数是处理很多property的不同的,所以,这里我们直接分析powered的处理。

[cpp]

} else if (g_str_equal("Powered", property)) {

gboolean powered;

//得到参数,这里就是1了

if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_BOOLEAN)

return btd_error_invalid_args(msg);

dbus_message_iter_get_basic(&sub, &powered);

//调用这个函数

return set_powered(conn, msg, powered, data);

}

下面就来看一下set_powered都做了些什么:

static DBusMessage *set_powered(DBusConnection *conn, DBusMessage *msg,

gboolean powered, void *data)

{

struct btd_adapter *adapter = data;

uint8_t mode;

int err;

//就是先这个了

if (powered) {

//mode是off

mode = get_mode(&adapter->bdaddr, "on");

//所以,这个地方是传入的false

return set_discoverable(conn, msg, mode == MODE_DISCOVERABLE,

data);

}

……

return NULL;

}

static DBusMessage *set_discoverable(DBusConnection *conn, DBusMessage *msg,

gboolean discoverable, void *data)

{

struct btd_adapter *adapter = data;

uint8_t mode;

int err;

//这里discoverable是0,所以mode connectable

mode = discoverable ? MODE_DISCOVERABLE : MODE_CONNECTABLE;

//adapter的mode是off

if (mode == adapter->mode) {

adapter->global_mode = mode;

return dbus_message_new_method_return(msg);

}

//这里adapter的mode是off,mode是iteconnectable

err = set_mode(adapter, mode, msg);

/* when called by discov_timeout_handler(), msg may be NULL, and cause dbus error */

if (err < 0 && msg != NULL)

return btd_error_failed(msg, strerror(-err));

return NULL;

}

继续看

static int set_mode(struct btd_adapter *adapter, uint8_t new_mode,

DBusMessage *msg)

{

int err;

const char *modestr;

if (adapter->pending_mode != NULL)

return -EALREADY;

//我们是肯定up了,new mode为connectable

if (!adapter->up && new_mode != MODE_OFF) {

err = adapter_ops->set_powered(adapter->dev_id, TRUE);

if (err < 0)

return err;

goto done;

}

if (adapter->up && new_mode == MODE_OFF) {

err = adapter_ops->set_powered(adapter->dev_id, FALSE);

if (err < 0)

return err;

adapter->off_requested = TRUE;

goto done;

}

if (new_mode == adapter->mode)

return 0;

//new mode 是connectable,就是hciops中的set discoverable,同时因为discoverable是false,所以,就是page scan

err = adapter_set_mode(adapter, new_mode);

done:

//新的mode 是connectable

modestr = mode2str(new_mode);

//把它写入到config文件on mode中

write_device_mode(&adapter->bdaddr, modestr);

DBG("%s", modestr);

if (msg != NULL) {

struct session_req *req;

//用来看是否需要回给jni层内容,这里必然有一个

req = find_session_by_msg(adapter->mode_sessions, msg);

if (req) {

adapter->pending_mode = req;

session_ref(req);

} else

/* Wait for mode change to reply */

adapter->pending_mode = create_session(adapter,

connection, msg, new_mode, NULL);

} else

/* Nothing to reply just write the new mode */

adapter->mode = new_mode;

return 0;

}

所以,这里其实说白了就是发送了一个write scan enable的cmd,这个cmd的event我们在前文中都分析过了,会去read scan enable,然后通知上层pairable的property change。这个我们在2中进行分析。

2. 对pairable的property change的处理

同样的,property change的处理还是在eventloop中。

[cpp]

} else if (name.equals("Pairable") || name.equals("Discoverable")) {

//设置property的值

adapterProperties.setProperty(name, propValues[1]);

if (name.equals("Discoverable")) {

mBluetoothState.sendMessage(BluetoothAdapterStateMachine.SCAN_MODE_CHANGED);

}

//得到对应的值

String pairable = name.equals("Pairable") ? propValues[1] :

adapterProperties.getProperty("Pairable");

String discoverable = name.equals("Discoverable") ? propValues[1] :

adapterProperties.getProperty("Discoverable");

// This shouldn't happen, unless Adapter Properties are null.

if (pairable == null || discoverable == null)

return;

//这里开始的时候discoverable是false,pairable是true

int mode = BluetoothService.bluezStringToScanMode(

pairable.equals("true"),

discoverable.equals("true"));

if (mode >= 0) {

发送ACTION_SCAN_MODE_CHANGED的action

Intent intent = new Intent(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED);

intent.putExtra(BluetoothAdapter.EXTRA_SCAN_MODE, mode);

intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);

mContext.sendBroadcast(intent, BLUETOOTH_PERM);

}

所以,对pairable这一property change的反应就是发送了ACTION_SCAN_MODE_CHANGED的action。那么我们就来分析一下究竟有多少地方注册了这个action的receiver。

2.1 ACTION_SCAN_MODE_CHANGED的receiver分析

注册了这个action receiver的地方有:BluetoothDiscoverableEnabler。

2.1.1 BluetoothDiscoverableEnabler中receiver的分析

[cpp]

public void onReceive(Context context, Intent intent) {

if (BluetoothAdapter.ACTION_SCAN_MODE_CHANGED.equals(intent.getAction())) {

int mode = intent.getIntExtra(BluetoothAdapter.EXTRA_SCAN_MODE,

BluetoothAdapter.ERROR);

//只要不是error,就需要handle mode的changed

if (mode != BluetoothAdapter.ERROR) {

handleModeChanged(mode);

}

}

//mode changed的处理

void handleModeChanged(int mode) {

//打开的情况下,不会走到这,只有在后期设置可发现的时候,才会走到。UI上会显示一个可发现的倒计时吧。到了那时再具体分析,其实蛮简单的

if (mode == BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {

mDiscoverable = true;

updateCountdownSummary();

} else {

//这里的话,这里是false,这里就是显示两句话:

//1)假如没有配对设备,那么就是显示不让其他蓝牙设备检测到

//2)假如已经配对了设备,那么就是显示只让已配对的设备检测到

mDiscoverable = false;

setSummaryNotDiscoverable();

}

3 powered的property change的处理

同样的,对powered的property change的处理:

} else if (name.equals("Powered")) {

//就是发送POWER_STATE_CHANGED的msg。一看就知道是个state machine的msg,我们去看看吧mBluetoothState.sendMessage(BluetoothAdapterStateMachine.POWER_STATE_CHANGED,

propValues[1].equals("true") ? new Boolean(true) : new Boolean(false));

此时,statemachine处于swtiching的状态:

[cpp]

case POWER_STATE_CHANGED:

removeMessages(POWER_DOWN_TIMEOUT);

//这个if是false,我们是true,进else,我们在turnning on的状态,所以,没有什么好说的。

if (!((Boolean) message.obj)) {

if (mPublicState == BluetoothAdapter.STATE_TURNING_OFF) {

transitionTo(mHotOff);

finishSwitchingOff();

if (!mContext.getResources().getBoolean

(com.android.internal.R.bool.config_bluetooth_adapter_quick_switch)) {

deferMessage(obtainMessage(TURN_COLD));

}

}

} else {

if (mPublicState != BluetoothAdapter.STATE_TURNING_ON) {

if (mContext.getResources().getBoolean

(com.android.internal.R.bool.config_bluetooth_adapter_quick_switch)) {

recoverStateMachine(TURN_HOT, null);

} else {

recoverStateMachine(TURN_COLD, null);

}

}

}

break;

所以,在这里,整个powered的change并没有什么特别的处理。

4、 discoverable的property change的处理

这里discoveable是false,和上面pairable的处理时一个函数,只是多进入了一下这个函数:

[cpp]

if (name.equals("Discoverable")) {

mBluetoothState.sendMessage(BluetoothAdapterStateMachine.SCAN_MODE_CHANGED);

}

至于上层ui的改变,因为discoverable是false,所以,还是不会做什么改变。所以就不去分析了,我们仍然只分析BluetoothAdapterStateMachine.SCAN_MODE_CHANGED这个action的处理。

同样的,他仍然是一个adatperstatemachine的action,我们去swtiching的状态看看他的处理。

case SCAN_MODE_CHANGED:

// This event matches mBluetoothService.switchConnectable action

if (mPublicState == BluetoothAdapter.STATE_TURNING_ON) {

// set pairable if it's not

//假如pairable不是true,就去设置pairable,因为我们已经设置了,所以这就不会有什么了。

mBluetoothService.setPairable();

//这个函数在蓝牙的状态机装换中已经分析过,不再详细分析。

mBluetoothService.initBluetoothAfterTurningOn();

//转变到buetoothon的状态

transitionTo(mBluetoothOn);

//广播BluetoothAdapter.ACTION_STATE_CHANGED,这次的值是STATE_ON,所以,我们还是有必要再次分析一下的。

broadcastState(BluetoothAdapter.STATE_ON);

// run bluetooth now that it's turned on

// Note runBluetooth should be called only in adapter STATE_ON

//主要就是自动连接。其它也没有做什么特别的,见下面的简单分析

mBluetoothService.runBluetooth();

}

break;

/*package*/ void runBluetooth() {

//若是有可连接的设备,这里去进行自动连接。这个这里就不分析了

autoConnect();

// Log bluetooth on to battery stats.

//告诉电池管理那边,蓝牙打开了

long ident = Binder.clearCallingIdentity();

try {

mBatteryStats.noteBluetoothOn();

} catch (RemoteException e) {

Log.e(TAG, "", e);

} finally {

Binder.restoreCallingIdentity(ident);

}

}

我们在2.1.1中已经对BluetoothAdapter.ACTION_STATE_CHANGED这个action进行了详细的分析。它主要就是把ui上的按钮高亮了,其它还有一写profile会随着这个进行初始化,比如opp之类的,这里等到具体分析到的时候我们再详细的解释吧。

赞助本站

人工智能实验室

相关热词: android开发 教程

AiLab云推荐
展开

热门栏目HotCates

Copyright © 2010-2024 AiLab Team. 人工智能实验室 版权所有    关于我们 | 联系我们 | 广告服务 | 公司动态 | 免责声明 | 隐私条款 | 工作机会 | 展会港