这一篇文章粗略的讲解一下android4.2的BT打开/关闭的流程,文章可能有错误的地方,希望大家能指出;
如果对BT的代码分布或结构不大清楚的可以看我另一篇文章:
http://my.eoe.cn/cnhua5/archive/10607.html
其实了解了enable,disable也就差不多了;
假设开机之前上次蓝牙是打开的,这次开机会自动打开蓝牙。当然也可以在Setting中打开,这里为了简化流程;
在android系统启动过程中,在SystemServer中会去创建一个BluetoothManagerService服务,并且交由ServiceManager管理:
|
bluetooth = new BluetoothManagerService(context);
ServiceManager.addService(BluetoothAdapter.BLUETOOTH_MANAGER_SERVICE, bluetooth);
|
先来看看构造BluetoothManagerService这个过程:
BluetoothManagerService(Context context) {
mThread = new HandlerThread("BluetoothManager");
mThread.start();
mHandler = new BluetoothHandler(mThread.getLooper());
mContext = context;
mBluetooth = null;
mBinding = false;
mUnbinding = false;
mEnable = false;
mState = BluetoothAdapter.STATE_OFF;
mQuietEnableExternal = false;
mEnableExternal = false;
mAddress = null;
mName = null;
mContentResolver = context.getContentResolver();
mCallbacks = new RemoteCallbackList<IBluetoothManagerCallback>();
mStateChangeCallbacks = new RemoteCallbackList<IBluetoothStateChangeCallback>();
IntentFilter filter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
filter.addAction(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED);
filter.addAction(Intent.ACTION_USER_SWITCHED);
registerForAirplaneMode(filter);
mContext.registerReceiver(mReceiver, filter);
loadStoredNameAndAddress();
if (isBluetoothPersistedStateOn()) {
mEnableExternal = true;
}
}
首先启动一个Handler Thread,在class的说明中是这么写的:
/**
* Handy class for starting a new thread that has a looper. The looper can then be
* used to create handler classes. Note that start() must still be called.
*/
(启动一个有looper的thread,用来创建handler);
这里创建了一个BluetoothHandler,用来管理内部的各种消息处理。其中MESSAGE_ENABLE就是打开蓝牙的message。
|
mCallbacks = new RemoteCallbackList<IBluetoothManagerCallback>();
mStateChangeCallbacks = new RemoteCallbackList<IBluetoothStateChangeCallback>();
|
接下来new了两个回调函数集,暂时就这么叫吧。
然后注册了一个广播:
|
IntentFilter filter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
filter.addAction(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED);
filter.addAction(Intent.ACTION_USER_SWITCHED);
registerForAirplaneMode(filter);
mContext.registerReceiver(mReceiver, filter);
|
loadStoredNameAndAddress();看名字就知道是干嘛的了。BT会记住之前的配对。
|
if (isBluetoothPersistedStateOn()) {
mEnableExternal = true;
}
|
这句就关键了,就是你开机之前BT就是打开的状态,这里会做一个判断。并且置一个标志位。
在接收到ACTION_BOOT_COMPLETED广播时,会发送一个enable的msg;
1
2
3
4
5
6
7
8
9
10
11
12
13
|
synchronized(mReceiver) {
if (mEnableExternal && isBluetoothPersistedStateOnBluetooth()) {
//Enable
if (DBG) Log.d(TAG, "Auto-enabling Bluetooth.");
sendEnableMsg(mQuietEnableExternal);
}
}
if (!isNameAndAddressSet()) {
//Sync the Bluetooth name and address from the Bluetooth Adapter
if (DBG) Log.d(TAG,"Retrieving Bluetooth Adapter name and address...");
getNameAndAddress();
}
|
sendEnableMsg函数就是发送enable MSG,quietMode这个时候是false;
|
private void sendEnableMsg(boolean quietMode) {
mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_ENABLE,
quietMode ? 1 : 0, 0));
}
|
在BluetoothHandler收到MESSAGE_ENABLE消息后:
|
case MESSAGE_ENABLE:
mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE);
mEnable = true;
handleEnable(msg.arg1 == 1);
break;
|
下面进入 handleEnable(msg.arg1 == 1);看看:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
private void handleEnable(boolean quietMode) {
mQuietEnable = quietMode;
synchronized(mConnection) {
if ((mBluetooth == null) && (!mBinding)) {
//Start bind timeout and bind
Message timeoutMsg=mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND);
mHandler.sendMessageDelayed(timeoutMsg,TIMEOUT_BIND_MS);
mConnection.setGetNameAddressOnly(false);
Intent i = new Intent(IBluetooth.class.getName());
if (!mContext.bindService(i, mConnection,Context.BIND_AUTO_CREATE,
UserHandle.USER_CURRENT)) {
mHandler.removeMessages(MESSAGE_TIMEOUT_BIND);
Log.e(TAG, "Fail to bind to: " + IBluetooth.class.getName());
} else {
mBinding = true;
}
} else if (mBluetooth != null) {
if (mConnection.isGetNameAddressOnly()) {
// if GetNameAddressOnly is set, we can clear this flag,
// so the service won't be unbind
// after name and address are saved
mConnection.setGetNameAddressOnly(false);
//Register callback object
try {
mBluetooth.registerCallback(mBluetoothCallback);
} catch (RemoteException re) {
Log.e(TAG, "Unable to register BluetoothCallback",re);
}
//Inform BluetoothAdapter instances that service is up
sendBluetoothServiceUpCallback();
}
//Enable bluetooth
try {
if (!mQuietEnable) {
if(!mBluetooth.enable()) {
Log.e(TAG,"IBluetooth.enable() returned false");
}
}
else {
if(!mBluetooth.enableNoAutoConnect()) {
Log.e(TAG,"IBluetooth.enableNoAutoConnect() returned false");
}
}
} catch (RemoteException e) {
Log.e(TAG,"Unable to call enable()",e);
}
}
}
}
|
第一次的时候mBluetooth==null && !mBinding;
|
Intent i = new Intent(IBluetooth.class.getName());
mContext.bindService(i, mConnection,Context.BIND_AUTO_CREATE, UserHandle.USER_CURRENT)
|
这里的IBluetooth实际上是AdapterService提供出来的接口供外部调用(IPC),具体的Service启动过程做的工作这里不详细跟踪,但是在这里必须要知道在AdapterService的OnCreate()里,调用了AdapterState.make()方法,这个方法是启动AdapterState的状态机,过程中会发送一个handler MSG,
|
sendMessageAtFrontOfQueue(obtainMessage(SM_INIT_CMD, mSmHandlerObj));
|
使mIsConstructionCompleted = true;在后面会用到。
|
mAdapterStateMachine = AdapterState.make(this, mAdapterProperties);
|
在Service起来后,就会和BluetoothManagerService的Context对象建立了连接,调用到
|
public void onServiceConnected(ComponentName className, IBinder service) {
if (DBG) Log.d(TAG, "BluetoothServiceConnection: connected to AdapterService");
Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_CONNECTED);
msg.obj = service;
mHandler.sendMessage(msg);
}
|
在BluetoothHandler中收到MESSAGE_BLUETOOTH_SERVICE_CONNECTED的MSG;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
|
case MESSAGE_BLUETOOTH_SERVICE_CONNECTED:
{
if (DBG) Log.d(TAG,"MESSAGE_BLUETOOTH_SERVICE_CONNECTED");
//Remove timeout
mHandler.removeMessages(MESSAGE_TIMEOUT_BIND);
IBinder service = (IBinder) msg.obj;
synchronized(mConnection) {
mBinding = false;
mBluetooth = IBluetooth.Stub.asInterface(service);
if (mConnection.isGetNameAddressOnly()) {
//Request GET NAME AND ADDRESS
Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS);
mHandler.sendMessage(getMsg);
if (!mEnable) return;
}
mConnection.setGetNameAddressOnly(false);
//Register callback object
try {
mBluetooth.registerCallback(mBluetoothCallback);
} catch (RemoteException re) {
Log.e(TAG, "Unable to register BluetoothCallback",re);
}
//Inform BluetoothAdapter instances that service is up
sendBluetoothServiceUpCallback();
//Do enable request
try {
if (mQuietEnable == false) {
if(!mBluetooth.enable()) {
Log.e(TAG,"IBluetooth.enable() returned false");
}
}
else
{
if(!mBluetooth.enableNoAutoConnect()) {
Log.e(TAG,"IBluetooth.enableNoAutoConnect() returned false");
}
}
} catch (RemoteException e) {
Log.e(TAG,"Unable to call enable()",e);
}
}
if (!mEnable) {
waitForOnOff(true, false);
handleDisable();
waitForOnOff(false, false);
}
break;
}
|
获取mBluetooth这个Binder Server的代理对象,接下来注册CallBack,sendBluetoothServiceUpCallback()函数是用来通知BluetoothAdapter对象Service已经起来了,然后就调用到了AdapterService的enable()函数了,来看下:
|
public synchronized boolean enable(boolean quietMode) {
enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
"Need BLUETOOTH ADMIN permission");
if (DBG)debugLog("Enable called with quiet mode status = " + mQuietmode);
mQuietmode = quietMode;
Message m =
mAdapterStateMachine.obtainMessage(AdapterState.USER_TURN_ON);
mAdapterStateMachine.sendMessage(m);
return true;
}
|
这里有一个AdapterState,它是一个状态机,用来管理BluetoothAdapter的状态。
|
This state machine handles Bluetooth Adapter State.
|
AdapterState父类StateMachine收到USER_TURN_ON的MSG,交由SmHandler处理,
|
@Override
public final void handleMessage(Message msg) {
if (mDbg) Log.d(TAG, "handleMessage: E msg.what=" + msg.what);
/** Save the current message */
mMsg = msg;
if (mIsConstructionCompleted) {
/** Normal path */
processMsg(msg);
} else if (!mIsConstructionCompleted &&
(mMsg.what == SM_INIT_CMD) && (mMsg.obj == mSmHandlerObj)) {
/** Initial one time path. */
mIsConstructionCompleted = true;
invokeEnterMethods(0);
} else {
throw new RuntimeException("StateMachine.handleMessage: " +
"The start method not called, received msg: " + msg);
}
performTransitions();
if (mDbg) Log.d(TAG, "handleMessage: X");
}
|
由前面我们知道,在AdapterService启动的时候,已经把mIsConstructionCompleted标志位设为ture了。所以这里会走到processMsg()函数。
|
/**
* Process the message. If the current state doesn't handle
* it, call the states parent and so on. If it is never handled then
* call the state machines unhandledMessage method.
*/
private final void processMsg(Message msg) {
StateInfo curStateInfo = mStateStack[mStateStackTopIndex];
if (mDbg) {
Log.d(TAG, "processMsg: " + curStateInfo.state.getName());
}
if (isQuit(msg)) {
transitionTo(mQuittingState);
} else {
while (!curStateInfo.state.processMessage(msg)) {
/**
* Not processed
*/
curStateInfo = curStateInfo.parentStateInfo;
if (curStateInfo == null) {
/**
* No parents left so it's not handled
*/
mSm.unhandledMessage(msg);
break;
}
if (mDbg) {
Log.d(TAG, "processMsg: " + curStateInfo.state.getName());
}
}
/**
* Record that we processed the message
*/
if (mSm.recordLogRec(msg)) {
if (curStateInfo != null) {
State orgState = mStateStack[mStateStackTopIndex].state;
mLogRecords.add(msg, mSm.getLogRecString(msg), curStateInfo.state,
orgState);
} else {
mLogRecords.add(msg, mSm.getLogRecString(msg), null, null);
}
}
}
}
|
这里会根据当前置顶的状态来分配执行路线,因为BT当前是OFF状态,会走到OffState类的processMessage()方法:
|
private class OffState extends State {
@Override
public void enter() {
infoLog("Entering OffState");
}
@Override
public boolean processMessage(Message msg) {
switch(msg.what) {
case USER_TURN_ON:
if (DBG) Log.d(TAG,"CURRENT_STATE=OFF, MESSAGE = USER_TURN_ON");
notifyAdapterStateChange(BluetoothAdapter.STATE_TURNING_ON);
mPendingCommandState.setTurningOn(true);
transitionTo(mPendingCommandState);
sendMessageDelayed(START_TIMEOUT, START_TIMEOUT_DELAY);
mAdapterService.processStart();
break;
case USER_TURN_OFF:
if (DBG) Log.d(TAG,"CURRENT_STATE=OFF, MESSAGE = USER_TURN_OFF");
//TODO: Handle case of service started and stopped without enable
break;
default:
if (DBG) Log.d(TAG,"ERROR: UNEXPECTED MESSAGE: CURRENT_STATE=OFF, MESSAGE = " + msg.what );
return false;
}
return true;
}
}
|
这里会把状态机状态过渡到PendingCommandState,其中notifyAdapterStateChange()就是往上层发送BT state变化的广播,然后调用AdapterService的processStart();
|
void processStart() {
if (DBG) debugLog("processStart()");
Class[] supportedProfileServices = Config.getSupportedProfiles();
//Initialize data objects
for (int i=0; i < supportedProfileServices.length;i++) {
mProfileServicesState.put(supportedProfileServices[i].getName(),BluetoothAdapter.STATE_OFF);
}
mRemoteDevices = new RemoteDevices(this);
mAdapterProperties.init(mRemoteDevices);
if (DBG) {debugLog("processStart(): Make Bond State Machine");}
mBondStateMachine = BondStateMachine.make(this, mAdapterProperties, mRemoteDevices);
mJniCallbacks.init(mBondStateMachine,mRemoteDevices);
//FIXME: Set static instance here???
setAdapterService(this);
//Start profile services
if (!mProfilesStarted && supportedProfileServices.length >0) {
//Startup all profile services
setProfileServiceState(supportedProfileServices,BluetoothAdapter.STATE_ON);
}else {
if (DBG) {debugLog("processStart(): Profile Services alreay started");}
mAdapterStateMachine.sendMessage(mAdapterStateMachine.obtainMessage(AdapterState.STARTED));
}
}
|
这里会缓存ProfileServicesState,BT支持的某些Profile Service状态,初始化remoteDevices,创建启动BondStateMachine状态机,它的类描述是
|
This state machine handles Bluetooth Adapter State. States: StableState : No device is in bonding / unbonding state. PendingCommandState : Some device is in bonding / unbonding state. TODO(BT) This class can be removed and this logic moved to the stack.
|
,还会初始化jni回调,其实就是让jniCallbacks知道了我已经有了remoteDevices和bondStateMachine对象了可以使用了,接下来会
|
setProfileServiceState(supportedProfileServices,BluetoothAdapter.STATE_ON);
|
也就是会启动Profiles的Service,下面重点看它。
|
private void setProfileServiceState(Class[] services, int state) {
if (state != BluetoothAdapter.STATE_ON && state != BluetoothAdapter.STATE_OFF) {
Log.w(TAG,"setProfileServiceState(): invalid state...Leaving...");
return;
}
int expectedCurrentState= BluetoothAdapter.STATE_OFF;
int pendingState = BluetoothAdapter.STATE_TURNING_ON;
if (state == BluetoothAdapter.STATE_OFF) {
expectedCurrentState= BluetoothAdapter.STATE_ON;
pendingState = BluetoothAdapter.STATE_TURNING_OFF;
}
for (int i=0; i <services.length;i++) {
String serviceName = services[i].getName();
Integer serviceState = mProfileServicesState.get(serviceName);
if(serviceState != null && serviceState != expectedCurrentState) {
Log.w(TAG, "Unable to " + (state == BluetoothAdapter.STATE_OFF? "start" : "stop" ) +" service " +
serviceName+". Invalid state: " + serviceState);
continue;
}
if (DBG) {
Log.w(TAG, (state == BluetoothAdapter.STATE_OFF? "Stopping" : "Starting" ) +" service " +
serviceName);
}
mProfileServicesState.put(serviceName,pendingState);
Intent intent = new Intent(this,services[i]);
intent.putExtra(EXTRA_ACTION,ACTION_SERVICE_STATE_CHANGED);
intent.putExtra(BluetoothAdapter.EXTRA_STATE,state);
startService(intent);
}
}
|
setProfileServiceState()走下来,pendingState是BluetoothAdapter.STATE_TURNING_ON;state是BluetoothAdapter.STATE_ON;然后就会启动所有的Profiles Service。在ProfileService类的OnStartCommand()中会调用到其DoStart()函数,AdapterState会通知MESSAGE_PROFILE_SERVICE_STATE_CHANGED消息,最终处理在AdapterService的processProfileServiceStateChanged()方法中的isTurningOn的else分支:
|
else if (isTurningOn) {
//Process start pending
//Check if all services are started if so, update state
//if (DBG) Log.d(TAG,"Checking if all profiles are running...");
synchronized (mProfileServicesState) {
Iterator<Map.Entry<String,Integer>> i = mProfileServicesState.entrySet().iterator();
while (i.hasNext()) {
Map.Entry<String,Integer> entry = i.next();
if (BluetoothAdapter.STATE_ON != entry.getValue()) {
Log.d(TAG, "Profile still not running:" + entry.getKey());
return;
}
}
}
if (DBG) Log.d(TAG, "All profile services started.");
mProfilesStarted=true;
//Send message to state machine
mAdapterStateMachine.sendMessage(mAdapterStateMachine.obtainMessage(AdapterState.STARTED));
}
|
因为这个时候AdapterState状态机PendingCommandState置顶,所以MSG会被它收到并处理:
|
case STARTED: {
if (DBG) Log.d(TAG,"CURRENT_STATE=PENDING, MESSAGE = STARTED, isTurningOn=" + isTurningOn + ", isTurningOff=" + isTurningOff);
//Remove start timeout
removeMessages(START_TIMEOUT);
//Enable
boolean ret = mAdapterService.enableNative();
if (!ret) {
Log.e(TAG, "Error while turning Bluetooth On");
notifyAdapterStateChange(BluetoothAdapter.STATE_OFF);
transitionTo(mOffState);
} else {
sendMessageDelayed(ENABLE_TIMEOUT, ENABLE_TIMEOUT_DELAY);
}
break;
|
终于------->
boolean ret = mAdapterService.enableNative();
接下来就是通过JNI的调用了,通过上一篇文章我们知道其对应的jni为
packages/app/Bluetooth/jni/com_android_bluetooth_btservice_AdapterService.cpp;
|
static jboolean enableNative(JNIEnv* env, jobject obj) {
ALOGV("%s:",__FUNCTION__);
jboolean result = JNI_FALSE;
if (!sBluetoothInterface) return result;
int ret = sBluetoothInterface->enable();
result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
return result;
}
|
sBluetoothInterface是一个bt_interface_t结构体,定义位于hardware/libhardware/include/hardware/bluetooth.h;
|
typedef struct {
/** set to sizeof(bt_interface_t) */
size_t size;
/**
* Opens the interface and provides the callback routines
* to the implemenation of this interface.
*/
int (*init)(bt_callbacks_t* callbacks );
/** Enable Bluetooth. */
int (*enable)(void);
/** Disable Bluetooth. */
int (*disable)(void);
/** Closes the interface. */
void (*cleanup)(void);
/** Get all Bluetooth Adapter properties at init */
int (*get_adapter_properties)(void);
/** Get Bluetooth Adapter property of 'type' */
int (*get_adapter_property)(bt_property_type_t type);
/** Set Bluetooth Adapter property of 'type' */
/* Based on the type, val shall be one of
* bt_bdaddr_t or bt_bdname_t or bt_scanmode_t etc
*/
int (*set_adapter_property)(const bt_property_t *property);
/** Get all Remote Device properties */
int (*get_remote_device_properties)(bt_bdaddr_t *remote_addr);
/** Get Remote Device property of 'type' */
int (*get_remote_device_property)(bt_bdaddr_t *remote_addr,
bt_property_type_t type);
/** Set Remote Device property of 'type' */
int (*set_remote_device_property)(bt_bdaddr_t *remote_addr,
const bt_property_t *property);
/** Get Remote Device's service record for the given UUID */
int (*get_remote_service_record)(bt_bdaddr_t *remote_addr,
bt_uuid_t *uuid);
/** Start SDP to get remote services */
int (*get_remote_services)(bt_bdaddr_t *remote_addr);
/** Start Discovery */
int (*start_discovery)(void);
/** Cancel Discovery */
int (*cancel_discovery)(void);
/** Create Bluetooth Bonding */
int (*create_bond)(const bt_bdaddr_t *bd_addr);
/** Remove Bond */
int (*remove_bond)(const bt_bdaddr_t *bd_addr);
/** Cancel Bond */
int (*cancel_bond)(const bt_bdaddr_t *bd_addr);
/** BT Legacy PinKey Reply */
/** If accept==FALSE, then pin_len and pin_code shall be 0x0 */
int (*pin_reply)(const bt_bdaddr_t *bd_addr, uint8_t accept,
uint8_t pin_len, bt_pin_code_t *pin_code);
/** BT SSP Reply - Just Works, Numeric Comparison and Passkey
* passkey shall be zero for BT_SSP_VARIANT_PASSKEY_COMPARISON &
* BT_SSP_VARIANT_CONSENT
* For BT_SSP_VARIANT_PASSKEY_ENTRY, if accept==FALSE, then passkey
* shall be zero */
int (*ssp_reply)(const bt_bdaddr_t *bd_addr, bt_ssp_variant_t variant,
uint8_t accept, uint32_t passkey);
/** Get Bluetooth profile interface */
const void* (*get_profile_interface) (const char *profile_id);
/** Bluetooth Test Mode APIs - Bluetooth must be enabled for these APIs */
/* Configure DUT Mode - Use this mode to enter/exit DUT mode */
int (*dut_mode_configure)(uint8_t enable);
/* Send any test HCI (vendor-specific) command to the controller. Must be in DUT Mode */
int (*dut_mode_send)(uint16_t opcode, uint8_t *buf, uint8_t len);
} bt_interface_t;
|
这个函数会调用到external/bluetooth/bluedroid/btif/src/bluetooth.c下,但是这个是如何调用到这里的我确实挺糊涂的,我对C也半熟不懂的;
|
static int enable( void )
{
ALOGI("enable");
/* sanity check */
if (interface_ready() == FALSE)
return BT_STATUS_NOT_READY;
return btif_enable_bluetooth();
}
|
再往下就是调用external/bluetooth/bluedroid/btif/src/btif—_core.c
的btif_enable_bluetooth函数;
|
bt_status_t btif_enable_bluetooth(void)
{
BTIF_TRACE_DEBUG0("BTIF ENABLE BLUETOOTH");
if (btif_core_state != BTIF_CORE_STATE_DISABLED)
{
ALOGD("not disabledn");
return BT_STATUS_DONE;
}
btif_core_state = BTIF_CORE_STATE_ENABLING;
/* Create the GKI tasks and run them */
bte_main_enable(btif_local_bd_addr.address);
return BT_STATUS_SUCCESS;
}
|
BT stack这一层我的理解不清楚,就不误导人了啊,有机会会更多的去了解的。
蓝牙的统一内核接口(GKI),蓝牙芯片厂商通过GKI快速轻松的移植蓝牙协议栈到其他操作系统上;
最后,disable和enable的过程大差不差,所以就不详细记录了。总的来说,4.2以后的BT结构的变化,BT stack的变化导致去除了bluez,现在的架构调用流程更加的清晰分明,也更好理解了。