Android -- AdapterService之藍牙啓動過程分析
前面介紹BluetoothManagerService啓動過程enable BT的部分提到,處理ENABLE msg的最終調用主要是call到AdapterService註冊IBluetoothCallback回調監聽藍牙使能狀態、以及AdapterService::enable()接口開啓藍牙,下面就接着這部分往下看。
AdapterService是Service的子類,Bind service會觸發依次調用它的聲明週期函數onCreate() -> onBind():
public class AdapterService extends Service {
......
static {
classInitNative();//native層的init部分
}
......
@Override
public void onCreate() {
super.onCreate();
debugLog("onCreate()");
mRemoteDevices = new RemoteDevices(this, Looper.getMainLooper());//重要類型,它實現了接受stack反饋的device信息變化的回調,比如UUID
mRemoteDevices.init();
mBinder = new AdapterServiceBinder(this);//AdapterService內部封裝的IBluetooth接口實現者
mAdapterProperties = new AdapterProperties(this);//管理當前Adapter的一些屬性,比如配對的device,uuid信息等;有些接口供stack回調上報狀態使用
mAdapterStateMachine = AdapterState.make(this);//一個簡單的StateMachine,處理開關BT中間的狀態切換
mJniCallbacks = new JniCallbacks(this, mAdapterProperties);//stack會通過此對象上報一些bt狀態和信息
initNative();//native層的init工作
......
// Phone policy is specific to phone implementations and hence if a device wants to exclude
// it out then it can be disabled by using the flag below.
if (getResources().getBoolean(com.android.bluetooth.R.bool.enable_phone_policy)) {
Log.i(TAG, "Phone policy enabled");
mPhonePolicy = new PhonePolicy(this, new ServiceFactory());//啓動PhonePolicy,它會根據觸發重連之前的設備;在available的設備之間處理連接切換等
mPhonePolicy.start();
} else {
Log.i(TAG, "Phone policy disabled");
}
mActiveDeviceManager = new ActiveDeviceManager(this, new ServiceFactory());//處理Active Device的管理類;比如Android默認可以連接多個sink設備,但只有一個出聲,這個就是active的device;
//要通過AudioManager的接口告知Audio當前系統哪個device是active的,這樣Audio系統才能根據策略選擇正確的設備播放音頻
mActiveDeviceManager.start();
setAdapterService(this);//保存當前的AdapterServie實例,因爲其他的類裏可能要獲取它
......
}
......
@Override
public IBinder onBind(Intent intent) {
debugLog("onBind()");
return mBinder;
}
......
/**
* Handlers for incoming service calls
*/
private AdapterServiceBinder mBinder;
/**
* The Binder implementation must be declared to be a static class, with
* the AdapterService instance passed in the constructor. Furthermore,
* when the AdapterService shuts down, the reference to the AdapterService
* must be explicitly removed.
*
* Otherwise, a memory leak can occur from repeated starting/stopping the
* service...Please refer to android.os.Binder for further details on
* why an inner instance class should be avoided.
*
*/
private static class AdapterServiceBinder extends IBluetooth.Stub {
private AdapterService mService;
AdapterServiceBinder(AdapterService svc) {
mService = svc;
}
public void cleanup() {
mService = null;
}
public AdapterService getService() {
if (mService != null && mService.isAvailable()) {
return mService;
}
return null;
}
......
@Override
public boolean enable() {
if ((Binder.getCallingUid() != Process.SYSTEM_UID) && (!Utils.checkCaller())) {
Log.w(TAG, "enable() - Not allowed for non-active user and non system user");
return false;
}
AdapterService service = getService();
if (service == null) {
return false;
}
return service.enable();
}
......
}
}
}
從code看出,BluetoothManagerService先獲取到IBinder對象,再通過它調用AdapterService的對於方法完成工作。爲了較好的跟flow,我們先看初始化部分;其他的細節可以參考註釋:
加載AdapterService類時,需要完成的static代碼塊調用:
static {
classInitNative();
}
......
static void classInitNative(JNIEnv* env, jclass clazz) {
jclass jniUidTrafficClass = env->FindClass("android/bluetooth/UidTraffic");
android_bluetooth_UidTraffic.constructor =
env->GetMethodID(jniUidTrafficClass, "<init>", "(IJJ)V");
jclass jniCallbackClass =
env->FindClass("com/android/bluetooth/btservice/JniCallbacks");
sJniCallbacksField = env->GetFieldID(
clazz, "mJniCallbacks", "Lcom/android/bluetooth/btservice/JniCallbacks;");//獲取AdapterService中的mJniCallbacks實例,通知上層stack的變化信息
method_stateChangeCallback =
env->GetMethodID(jniCallbackClass, "stateChangeCallback", "(I)V");//
method_adapterPropertyChangedCallback = env->GetMethodID(
jniCallbackClass, "adapterPropertyChangedCallback", "([I[[B)V");
method_discoveryStateChangeCallback = env->GetMethodID(
jniCallbackClass, "discoveryStateChangeCallback", "(I)V");
method_devicePropertyChangedCallback = env->GetMethodID(
jniCallbackClass, "devicePropertyChangedCallback", "([B[I[[B)V");
method_deviceFoundCallback =
env->GetMethodID(jniCallbackClass, "deviceFoundCallback", "([B)V");
method_pinRequestCallback =
env->GetMethodID(jniCallbackClass, "pinRequestCallback", "([B[BIZ)V");
method_sspRequestCallback =
env->GetMethodID(jniCallbackClass, "sspRequestCallback", "([B[BIII)V");
method_bondStateChangeCallback =
env->GetMethodID(jniCallbackClass, "bondStateChangeCallback", "(I[BI)V");
method_aclStateChangeCallback =
env->GetMethodID(jniCallbackClass, "aclStateChangeCallback", "(I[BI)V");
method_setWakeAlarm = env->GetMethodID(clazz, "setWakeAlarm", "(JZ)Z");
method_acquireWakeLock =
env->GetMethodID(clazz, "acquireWakeLock", "(Ljava/lang/String;)Z");
method_releaseWakeLock =
env->GetMethodID(clazz, "releaseWakeLock", "(Ljava/lang/String;)Z");
method_energyInfo = env->GetMethodID(
clazz, "energyInfoCallback", "(IIJJJJ[Landroid/bluetooth/UidTraffic;)V");
if (hal_util_load_bt_library((bt_interface_t const**)&sBluetoothInterface)) {//加載bt stack的so,獲取操作句柄sBluetoothInterface;用以調用stack的接口完成操作
ALOGE("No Bluetooth Library found");
}
}
這部分初始化工作,從code看很清晰;主要做兩件事:
- 在Jni層獲取AdapterService中的callback接口,當stack上報狀態時,需要通過這些接口反饋到framework層
- 解析bt so,獲取它暴露給上層的接口,用來將framework的操作請求真正下發到協議棧中。主要是dlopen方式操作so、拿到操作handle的,source code部分主要在Pie_9.0.0_r3\system\bt\main中
bt_interface_t類型定義的都是上層會涉及到的bt操作,如果connect/disconnect、createBond/removeBond等,最終都會此類型將請求下發到協議棧中:
/** Represents the standard Bluetooth DM interface. */
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)(bool guest_mode);
/** Disable Bluetooth. */
int (*disable)(void);
/** Closes the interface. */
void (*cleanup)(void);
/** Remove Bond */
int (*remove_bond)(const RawAddress* bd_addr);
/** Cancel Bond */
int (*cancel_bond)(const RawAddress* bd_addr);
/**
* Get the connection status for a given remote device.
* return value of 0 means the device is not connected,
* non-zero return status indicates an active connection.
*/
int (*get_connection_state)(const RawAddress* bd_addr);
/** Read Energy info details - return value indicates BT_STATUS_SUCCESS or
* BT_STATUS_NOT_READY Success indicates that the VSC command was sent to
* controller
*/
int (*read_energy_info)();
/**
* Get the AvrcpTarget Service interface to interact with the Avrcp Service
*/
bluetooth::avrcp::ServiceInterface* (*get_avrcp_service)(void);
} bt_interface_t;
靜態初始化塊完成後,就是Service::onCreate()的調用,除了前面提到的初始化一些重要的Java對象外,還會做一些Native層的初始化:
static bool initNative(JNIEnv* env, jobject obj) {
ALOGV("%s", __func__);
android_bluetooth_UidTraffic.clazz =
(jclass)env->NewGlobalRef(env->FindClass("android/bluetooth/UidTraffic"));
sJniAdapterServiceObj = env->NewGlobalRef(obj);
sJniCallbacksObj =
env->NewGlobalRef(env->GetObjectField(obj, sJniCallbacksField));
if (!sBluetoothInterface) {
return JNI_FALSE;
}
int ret = sBluetoothInterface->init(&sBluetoothCallbacks);//將需要的一些callback函數註冊到stack中,這樣stack就可以通過這些函數上報此類事件
if (ret != BT_STATUS_SUCCESS) {
ALOGE("Error while setting the callbacks: %d\n", ret);
sBluetoothInterface = NULL;
return JNI_FALSE;
}
ret = sBluetoothInterface->set_os_callouts(&sBluetoothOsCallouts);//將需要的一些callback函數註冊到stack中,這樣stack就可以通過這些函數上報此類事件
if (ret != BT_STATUS_SUCCESS) {
ALOGE("Error while setting Bluetooth callouts: %d\n", ret);
sBluetoothInterface->cleanup();
sBluetoothInterface = NULL;
return JNI_FALSE;
}
......
static bt_callbacks_t sBluetoothCallbacks = {
sizeof(sBluetoothCallbacks), adapter_state_change_callback,
adapter_properties_callback, remote_device_properties_callback,
device_found_callback, discovery_state_changed_callback,
pin_request_callback, ssp_request_callback,
bond_state_changed_callback, acl_state_changed_callback,
callback_thread_event, dut_mode_recv_callback,
le_test_mode_recv_callback, energy_info_recv_callback};
......
static bt_os_callouts_t sBluetoothOsCallouts = {
sizeof(sBluetoothOsCallouts), set_wake_alarm_callout,
acquire_wake_lock_callout, release_wake_lock_callout,
};
將stack需要用到的一些callback函數註冊給它,這樣在需要的時候,stack就可以通過調用這些函數將信息反饋到上層了。
這條路串起來之後,再回頭看AdapterService::enable():
public synchronized boolean enable(boolean quietMode) {
enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission");
// Enforce the user restriction for disallowing Bluetooth if it was set.
if (mUserManager.hasUserRestriction(UserManager.DISALLOW_BLUETOOTH, UserHandle.SYSTEM)) {
debugLog("enable() called when Bluetooth was disallowed");
return false;
}
debugLog("enable() - Enable called with quiet mode status = " + quietMode);
mQuietmode = quietMode;
mAdapterStateMachine.sendMessage(AdapterState.BLE_TURN_ON);
return true;
}
可以看到只是簡單的向AdapterState發送一個BLE_TURN_ON msg,隨機進入狀態機去處理;
/**
* This state machine handles Bluetooth Adapter State.
* Stable States:
* {@link OffState}: Initial State
* {@link BleOnState} : Bluetooth Low Energy, Including GATT, is on
* {@link OnState} : Bluetooth is on (All supported profiles)
*
* Transition States:
* {@link TurningBleOnState} : OffState to BleOnState
* {@link TurningBleOffState} : BleOnState to OffState
* {@link TurningOnState} : BleOnState to OnState
* {@link TurningOffState} : OnState to BleOnState
*
* +------ Off <-----+
* | |
* v |
* TurningBleOn TO---> TurningBleOff
* | ^ ^
* | | |
* +-----> ----+ |
* BleOn |
* +------ <---+ O
* v | T
* TurningOn TO----> TurningOff
* | ^
* | |
* +-----> On ------+
*
*/
從上圖AdapterState的註釋及code,我們知道以下幾點:
- AdapterState中所有State的父類都是BaseAdapterState,所以在enter某個狀態機時,會先調用此父類的enter()接口;同時,在exit某個狀態機時,也會call此父類的exit()接口
- 默認的初始化狀態時Off狀態,也就是此時BT尚未啓動
- 因爲AdapterState是管理BT啓動的邏輯主要部分,所以向外通知當前BT使能進程的消息,應該在這裏觸發比較合理
因爲在某個狀態節點,我們都應該向外通知狀態,所以這部分被封裝到了父類State中:
AdapterState:
private abstract class BaseAdapterState extends State {
abstract int getStateValue();
@Override
public void enter() {
int currState = getStateValue();
infoLog("entered ");
mAdapterService.updateAdapterState(mPrevState, currState);//通過AdapterService向外通知BT使能的狀態信息
mPrevState = currState;
}
......
}
AdapterService:
void updateAdapterState(int prevState, int newState) {//如果某個服務對藍牙啓動狀態過程感興趣,它就應該註冊IBluetootCallback對象;跟BluetoothManagerService一樣
mAdapterProperties.setState(newState);
if (mCallbacks != null) {
int n = mCallbacks.beginBroadcast();
debugLog("updateAdapterState() - Broadcasting state " + BluetoothAdapter.nameForState(
newState) + " to " + n + " receivers.");
for (int i = 0; i < n; i++) {
try {
mCallbacks.getBroadcastItem(i).onBluetoothStateChange(prevState, newState);//調用onBluetoothStateChange()回調狀態變化
} catch (RemoteException e) {
debugLog("updateAdapterState() - Callback #" + i + " failed (" + e + ")");
}
}
mCallbacks.finishBroadcast();
}
......
}
BluetoothManagerService:
private final IBluetoothCallback mBluetoothCallback = new IBluetoothCallback.Stub() {
@Override
public void onBluetoothStateChange(int prevState, int newState) throws RemoteException {
Message msg =
mHandler.obtainMessage(MESSAGE_BLUETOOTH_STATE_CHANGE, prevState, newState);//發送MESSAGE_BLUETOOTH_STATE_CHANGE
mHandler.sendMessage(msg);
}
};
這裏我們發送的是BLE_TURN_ON msg,看它的處理:
private class OffState extends BaseAdapterState {
@Override
int getStateValue() {
return BluetoothAdapter.STATE_OFF;
}
@Override
public boolean processMessage(Message msg) {
switch (msg.what) {
case BLE_TURN_ON:
transitionTo(mTurningBleOnState);
break;
default:
infoLog("Unhandled message - " + messageString(msg.what));
return false;
}
return true;
}
}
......
private class TurningBleOnState extends BaseAdapterState {
@Override
int getStateValue() {
return BluetoothAdapter.STATE_BLE_TURNING_ON;
}
@Override
public void enter() {
super.enter();
sendMessageDelayed(BLE_START_TIMEOUT, BLE_START_TIMEOUT_DELAY);
mAdapterService.bringUpBle();
}
@Override
public void exit() {
removeMessages(BLE_START_TIMEOUT);
super.exit();
}
@Override
public boolean processMessage(Message msg) {
switch (msg.what) {
case BLE_STARTED:
transitionTo(mBleOnState);
break;
case BLE_START_TIMEOUT:
errorLog(messageString(msg.what));
transitionTo(mTurningBleOffState);
break;
default:
infoLog("Unhandled message - " + messageString(msg.what));
return false;
}
return true;
}
}
......
}
BLE_TURN_ON的消息處理是transferTo TurningBleOnState,它的enter()會調用mAdapterService.bringUpBle():
void bringUpBle() {
debugLog("bleOnProcessStart()");
if (getResources().getBoolean(
R.bool.config_bluetooth_reload_supported_profiles_when_enabled)) {
Config.init(getApplicationContext());
}
// Reset |mRemoteDevices| whenever BLE is turned off then on
// This is to replace the fact that |mRemoteDevices| was
// reinitialized in previous code.
//
// TODO(apanicke): The reason is unclear but
// I believe it is to clear the variable every time BLE was
// turned off then on. The same effect can be achieved by
// calling cleanup but this may not be necessary at all
// We should figure out why this is needed later
mRemoteDevices.reset();//RemoteDeivces管理對端設備的一些信息
mAdapterProperties.init(mRemoteDevices);//AdapterProperties管理當前Adapter的一些信息
debugLog("bleOnProcessStart() - Make Bond State Machine");
mBondStateMachine = BondStateMachine.make(this, mAdapterProperties, mRemoteDevices);//創建BondStateMachine對象,它負責管理一個device的配對過程
mJniCallbacks.init(mBondStateMachine, mRemoteDevices);//JniCallbacks主要負責監聽來自stack的callback信息,如設備配對狀態或設備更新UUID變化時,framework就可以收到回調
try {
mBatteryStats.noteResetBleScan();
} catch (RemoteException e) {
Log.w(TAG, "RemoteException trying to send a reset to BatteryStats");
}
StatsLog.write_non_chained(StatsLog.BLE_SCAN_STATE_CHANGED, -1, null,
StatsLog.BLE_SCAN_STATE_CHANGED__STATE__RESET, false, false, false);
//Start Gatt service
setProfileServiceState(GattService.class, BluetoothAdapter.STATE_ON);//啓動GattService服務,BLE設備需要GATT協議交換信息
}
除了創建一些重要對象外,這裏主要就是起到GattService了,Ble設備都需要通過GATT協議交換信息;其他可以參考上面的註釋。
Bluetooth framework聲明的Profile服務基本都是ProfileService的子類,所以參照Android Service的啓動過程,某個Profile啓動時,會調用到ProfileService的方法:
/**
* Base class for a background service that runs a Bluetooth profile
*/
public abstract class ProfileService extends Service {
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
......
if (state == BluetoothAdapter.STATE_OFF) {
doStop();//通知AdapterService的此Profile停止成功
} else if (state == BluetoothAdapter.STATE_ON) {
doStart();//通知AdapterService的此Profile啓動成功
}
}
return PROFILE_SERVICE_MODE;
}
private void doStart() {
......
mAdapterService.addProfile(this);//告知AdapterService此Profile啓動成功,更新Profile集合
......
mAdapterService.onProfileServiceStateChanged(this, BluetoothAdapter.STATE_ON);//通知AdapterService此Profile已啓動
}
private void doStop() {
......
if (mAdapterService != null) {
mAdapterService.onProfileServiceStateChanged(this, BluetoothAdapter.STATE_OFF);//通知AdapterService此Profile已停止
}
if (!stop()) {
Log.e(mName, "Unable to stop profile");
}
if (mAdapterService != null) {
mAdapterService.removeProfile(this);//告知AdapterService此Profile停止成功,更新Profile集合
}
......
stopSelf();
}
}
接着看AdapterService的處理:
/**
* Register a {@link ProfileService} with AdapterService.
*
* @param profile the service being added.
*/
public void addProfile(ProfileService profile) {
mHandler.obtainMessage(MESSAGE_PROFILE_SERVICE_REGISTERED, profile).sendToTarget();
}
/**
* Unregister a ProfileService with AdapterService.
*
* @param profile the service being removed.
*/
public void removeProfile(ProfileService profile) {
mHandler.obtainMessage(MESSAGE_PROFILE_SERVICE_UNREGISTERED, profile).sendToTarget();
}
/**
* Notify AdapterService that a ProfileService has started or stopped.
*
* @param profile the service being removed.
* @param state {@link BluetoothAdapter#STATE_ON} or {@link BluetoothAdapter#STATE_OFF}
*/
public void onProfileServiceStateChanged(ProfileService profile, int state) {
if (state != BluetoothAdapter.STATE_ON && state != BluetoothAdapter.STATE_OFF) {
throw new IllegalArgumentException(BluetoothAdapter.nameForState(state));
}
Message m = mHandler.obtainMessage(MESSAGE_PROFILE_SERVICE_STATE_CHANGED);
m.obj = profile;
m.arg1 = state;
mHandler.sendMessage(m);
}
private static final int MESSAGE_PROFILE_SERVICE_STATE_CHANGED = 1;
private static final int MESSAGE_PROFILE_SERVICE_REGISTERED = 2;
private static final int MESSAGE_PROFILE_SERVICE_UNREGISTERED = 3;
class AdapterServiceHandler extends Handler {
@Override
public void handleMessage(Message msg) {
debugLog("handleMessage() - Message: " + msg.what);
switch (msg.what) {
case MESSAGE_PROFILE_SERVICE_STATE_CHANGED:
debugLog("handleMessage() - MESSAGE_PROFILE_SERVICE_STATE_CHANGED");
processProfileServiceStateChanged((ProfileService) msg.obj, msg.arg1);
break;
case MESSAGE_PROFILE_SERVICE_REGISTERED:
debugLog("handleMessage() - MESSAGE_PROFILE_SERVICE_REGISTERED");
registerProfileService((ProfileService) msg.obj);
break;
case MESSAGE_PROFILE_SERVICE_UNREGISTERED:
debugLog("handleMessage() - MESSAGE_PROFILE_SERVICE_UNREGISTERED");
unregisterProfileService((ProfileService) msg.obj);
break;
}
}
private void registerProfileService(ProfileService profile) {
if (mRegisteredProfiles.contains(profile)) {
Log.e(TAG, profile.getName() + " already registered.");
return;
}
mRegisteredProfiles.add(profile);
}
private void unregisterProfileService(ProfileService profile) {
if (!mRegisteredProfiles.contains(profile)) {
Log.e(TAG, profile.getName() + " not registered (UNREGISTERED).");
return;
}
mRegisteredProfiles.remove(profile);
}
private void processProfileServiceStateChanged(ProfileService profile, int state) {
switch (state) {
case BluetoothAdapter.STATE_ON://此時是啓動GattService,所以是STATE_ON
if (!mRegisteredProfiles.contains(profile)) {
Log.e(TAG, profile.getName() + " not registered (STATE_ON).");
return;
}
if (mRunningProfiles.contains(profile)) {//防止重複啓動某個Profile
Log.e(TAG, profile.getName() + " already running.");
return;
}
mRunningProfiles.add(profile);
if (GattService.class.getSimpleName().equals(profile.getName())) {
enableNativeWithGuestFlag();//如果是啓動Gatt profile,則向stack下發enable bt的指令
} else if (mRegisteredProfiles.size() == Config.getSupportedProfiles().length
&& mRegisteredProfiles.size() == mRunningProfiles.size()) {//這裏是啓動Gatt以外的,在config.xml中聲明支持的其他Profile;相當於啓動BREDR mode
mAdapterProperties.onBluetoothReady();
updateUuids();
setBluetoothClassFromConfig();
mAdapterStateMachine.sendMessage(AdapterState.BREDR_STARTED);
}
break;
case BluetoothAdapter.STATE_OFF:
if (!mRegisteredProfiles.contains(profile)) {
Log.e(TAG, profile.getName() + " not registered (STATE_OFF).");
return;
}
if (!mRunningProfiles.contains(profile)) {
Log.e(TAG, profile.getName() + " not running.");
return;
}
mRunningProfiles.remove(profile);
// If only GATT is left, send BREDR_STOPPED.
if ((mRunningProfiles.size() == 1 && (GattService.class.getSimpleName()
.equals(mRunningProfiles.get(0).getName())))) {
mAdapterStateMachine.sendMessage(AdapterState.BREDR_STOPPED);
} else if (mRunningProfiles.size() == 0) {
disableNative();
mAdapterStateMachine.sendMessage(AdapterState.BLE_STOPPED);
}
break;
default:
Log.e(TAG, "Unhandled profile state: " + state);
}
}
}
處理enable 藍牙:
private void enableNativeWithGuestFlag() {
boolean isGuest = UserManager.get(this).isGuestUser();
if (!enableNative(isGuest)) {
Log.e(TAG, "enableNative() returned false");
}
}
static jboolean enableNative(JNIEnv* env, jobject obj, jboolean isGuest) {
ALOGV("%s", __func__);
if (!sBluetoothInterface) return JNI_FALSE;
int ret = sBluetoothInterface->enable(isGuest == JNI_TRUE ? 1 : 0);
return (ret == BT_STATUS_SUCCESS || ret == BT_STATUS_DONE) ? JNI_TRUE
: JNI_FALSE;
}
前面有介紹到stack的state回調會通過JNICallbacks對象回調上來,enable狀態也是如此:
final class JniCallbacks {
void stateChangeCallback(int status) {
mAdapterService.stateChangeCallback(status);
}
}
AdapterService:
void stateChangeCallback(int status) {
if (status == AbstractionLayer.BT_STATE_OFF) {
debugLog("stateChangeCallback: disableNative() completed");
} else if (status == AbstractionLayer.BT_STATE_ON) {//BT State on
mAdapterStateMachine.sendMessage(AdapterState.BLE_STARTED);
} else {
Log.e(TAG, "Incorrect status " + status + " in stateChangeCallback");
}
}
BT啓動之後,向AdapterState通知狀態,TurningBleOnState收到消息後,就會進入BleOnState;並對外通知狀態變化,如之前介紹,是通過AdapterService::updateAdapterState()函數處理:
void updateAdapterState(int prevState, int newState) {//如果某個服務對藍牙啓動狀態過程感興趣,它就應該註冊IBluetootCallback對象;跟BluetoothManagerService一樣
mAdapterProperties.setState(newState);
if (mCallbacks != null) {
int n = mCallbacks.beginBroadcast();
debugLog("updateAdapterState() - Broadcasting state " + BluetoothAdapter.nameForState(
newState) + " to " + n + " receivers.");
for (int i = 0; i < n; i++) {
try {
mCallbacks.getBroadcastItem(i).onBluetoothStateChange(prevState, newState);//調用onBluetoothStateChange()回調狀態變化
} catch (RemoteException e) {
debugLog("updateAdapterState() - Callback #" + i + " failed (" + e + ")");
}
}
mCallbacks.finishBroadcast();
}
// Turn the Adapter all the way off if we are disabling and the snoop log setting changed.
if (newState == BluetoothAdapter.STATE_BLE_TURNING_ON) {
mSnoopLogSettingAtEnable =
SystemProperties.getBoolean(BLUETOOTH_BTSNOOP_ENABLE_PROPERTY, false);
} else if (newState == BluetoothAdapter.STATE_BLE_ON
&& prevState != BluetoothAdapter.STATE_OFF) {
boolean snoopLogSetting =
SystemProperties.getBoolean(BLUETOOTH_BTSNOOP_ENABLE_PROPERTY, false);
if (mSnoopLogSettingAtEnable != snoopLogSetting) {
mAdapterStateMachine.sendMessage(AdapterState.BLE_TURN_OFF);
}
}
}
在介紹BluetoothManagerService時,我們就提到BMS會向AdapterService註冊一個callback來監聽BT的狀態:
private final IBluetoothCallback mBluetoothCallback = new IBluetoothCallback.Stub() {
@Override
public void onBluetoothStateChange(int prevState, int newState) throws RemoteException {
Message msg =
mHandler.obtainMessage(MESSAGE_BLUETOOTH_STATE_CHANGE, prevState, newState);//發送MESSAGE_BLUETOOTH_STATE_CHANGE
mHandler.sendMessage(msg);
}
};
處理Msg:
case MESSAGE_BLUETOOTH_STATE_CHANGE: {
int prevState = msg.arg1;
int newState = msg.arg2;
if (DBG) {
Slog.d(TAG,
"MESSAGE_BLUETOOTH_STATE_CHANGE: " + BluetoothAdapter.nameForState(
prevState) + " > " + BluetoothAdapter.nameForState(
newState));
}
mState = newState;
bluetoothStateChangeHandler(prevState, newState);//處理state變化
......
}
看bluetoothStateChangeHandler()的主要處理:
// Notify all proxy objects first of adapter state change
if (newState == BluetoothAdapter.STATE_BLE_ON || newState == BluetoothAdapter.STATE_OFF) {
boolean intermediate_off = (prevState == BluetoothAdapter.STATE_TURNING_OFF
&& newState == BluetoothAdapter.STATE_BLE_ON);
if (newState == BluetoothAdapter.STATE_OFF) {
// If Bluetooth is off, send service down event to proxy objects, and unbind
if (DBG) {
Slog.d(TAG, "Bluetooth is complete send Service Down");
}
sendBluetoothServiceDownCallback();
unbindAndFinish();
sendBleStateChanged(prevState, newState);
// Don't broadcast as it has already been broadcast before
isStandardBroadcast = false;
} else if (!intermediate_off) {//現在state是BLE_ON
// connect to GattService
if (DBG) {
Slog.d(TAG, "Bluetooth is in LE only mode");
}
if (mBluetoothGatt != null || !mContext.getPackageManager()
.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {//此時GattService只是啓動了,BMS還未拿到它的Binder操作句柄
continueFromBleOnState();
} else {
if (DBG) {
Slog.d(TAG, "Binding Bluetooth GATT service");
}
Intent i = new Intent(IBluetoothGatt.class.getName());
doBind(i, mConnection, Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT,
UserHandle.CURRENT);//這裏去Bind GattService,然後在BluetoothServiceConnection中觸發MESSAGE_BLUETOOTH_SERVICE_CONNECTED msg,並區分是SERVICE_IBLUETOOTHGATT
}
sendBleStateChanged(prevState, newState);
//Don't broadcase this as std intent
isStandardBroadcast = false;
} else if (intermediate_off) {
if (DBG) {
Slog.d(TAG, "Intermediate off, back to LE only mode");
}
// For LE only mode, broadcast as is
sendBleStateChanged(prevState, newState);
sendBluetoothStateCallback(false); // BT is OFF for general users
// Broadcast as STATE_OFF
newState = BluetoothAdapter.STATE_OFF;
sendBrEdrDownCallback();
}
}
BluetoothManagerService中Bind Profile的內容跟之前介紹的一樣,我們直接看處理:
case MESSAGE_BLUETOOTH_SERVICE_CONNECTED: {
if (DBG) {
Slog.d(TAG, "MESSAGE_BLUETOOTH_SERVICE_CONNECTED: " + msg.arg1);
}
IBinder service = (IBinder) msg.obj; //保存Service的onBinder()句柄
try {
mBluetoothLock.writeLock().lock();
if (msg.arg1 == SERVICE_IBLUETOOTHGATT) {
mBluetoothGatt =
IBluetoothGatt.Stub.asInterface(Binder.allowBlocking(service));//獲取GattService的句柄
continueFromBleOnState();//啓動BREDR的profile
break;
} // else must be SERVICE_IBLUETOOTH
}
獲取Gatt profile的Binder句柄,並調用continueFromBleOnState()去啓動其他的profile:
/**
* Call IBluetooth.onLeServiceUp() to continue if Bluetooth should be on.
*/
private void continueFromBleOnState() {
if (DBG) {
Slog.d(TAG, "continueFromBleOnState()");
}
try {
mBluetoothLock.readLock().lock();
if (mBluetooth == null) {
Slog.e(TAG, "onBluetoothServiceUp: mBluetooth is null!");
return;
}
if (isBluetoothPersistedStateOnBluetooth() || !isBleAppPresent()) {
// This triggers transition to STATE_ON
mBluetooth.onLeServiceUp();//調用onLeServiceUp()
persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH);
}
} catch (RemoteException e) {
Slog.e(TAG, "Unable to call onServiceUp", e);
} finally {
mBluetoothLock.readLock().unlock();
}
}
AdapterService:
void onLeServiceUp() {
mAdapterStateMachine.sendMessage(AdapterState.USER_TURN_ON);//發送USER_TURN_ON
}
//現在處於BleOnState,處理此消息進入TurningOnState
AdapterState:
private class TurningOnState extends BaseAdapterState {
@Override
int getStateValue() {
return BluetoothAdapter.STATE_TURNING_ON;
}
@Override
public void enter() {
super.enter();
sendMessageDelayed(BREDR_START_TIMEOUT, BREDR_START_TIMEOUT_DELAY);
mAdapterService.startProfileServices();
}
......
}
//啓動配置文件中定義的Profile:
AdapterService:
void startProfileServices() {
debugLog("startCoreServices()");
Class[] supportedProfileServices = Config.getSupportedProfiles();
if (supportedProfileServices.length == 1 && GattService.class.getSimpleName()
.equals(supportedProfileServices[0].getSimpleName())) {
mAdapterProperties.onBluetoothReady();
updateUuids();
setBluetoothClassFromConfig();
mAdapterStateMachine.sendMessage(AdapterState.BREDR_STARTED);
} else {
setAllProfileServiceStates(supportedProfileServices, BluetoothAdapter.STATE_ON);
}
}
最終的處理是啓動全部在Bluetooth.apk的config.xml中定義的Profile,Config.getSupportedProfiles()調用拿到的Profile集合就是聲明瞭true的Service:
<bool name="profile_supported_a2dp">true</bool>
<bool name="profile_supported_a2dp_sink">false</bool>
<bool name="profile_supported_hdp">true</bool>
<bool name="profile_supported_hs_hfp">true</bool>
<bool name="profile_supported_hfpclient">false</bool>
<bool name="profile_supported_hid_host">true</bool>
<bool name="profile_supported_opp">true</bool>
<bool name="profile_supported_pan">true</bool>
<bool name="profile_supported_pbap">true</bool>
<bool name="profile_supported_gatt">true</bool>
<bool name="pbap_include_photos_in_vcard">true</bool>
<bool name="pbap_use_profile_for_owner_vcard">true</bool>
<bool name="profile_supported_map">true</bool>
<bool name="profile_supported_avrcp_target">true</bool>
<bool name="profile_supported_avrcp_controller">false</bool>
<bool name="profile_supported_sap">false</bool>
<bool name="profile_supported_pbapclient">false</bool>
<bool name="profile_supported_mapmce">false</bool>
<bool name="profile_supported_hid_device">true</bool>
<bool name="profile_supported_hearing_aid">false</bool>
setAllProfileServiceStates()就是以STATE_ON的狀態啓動所有這些supported的Profile,它們也都是ProfileService的子類:
private void setAllProfileServiceStates(Class[] services, int state) {
for (Class service : services) {
if (GattService.class.getSimpleName().equals(service.getSimpleName())) {
continue;
}
setProfileServiceState(service, state);
}
}
所以也跟GattService啓動的flow類似,AdapterService會處理這些Profile的狀態變化,這裏是STATE_ON:
private void processProfileServiceStateChanged(ProfileService profile, int state) {
switch (state) {
case BluetoothAdapter.STATE_ON://此時是啓動GattService,所以是STATE_ON
if (!mRegisteredProfiles.contains(profile)) {
Log.e(TAG, profile.getName() + " not registered (STATE_ON).");
return;
}
if (mRunningProfiles.contains(profile)) {//防止重複啓動某個Profile
Log.e(TAG, profile.getName() + " already running.");
return;
}
mRunningProfiles.add(profile);
if (GattService.class.getSimpleName().equals(profile.getName())) {
enableNativeWithGuestFlag();//如果是啓動Gatt profile,則向stack下發enable bt的指令
} else if (mRegisteredProfiles.size() == Config.getSupportedProfiles().length
&& mRegisteredProfiles.size() == mRunningProfiles.size()) {//這裏是啓動Gatt以外的,在config.xml中聲明支持的其他Profile;相當於啓動BREDR mode
mAdapterProperties.onBluetoothReady();//Profile全部啓動完成,初始化變化,並設置當前Bt工作的mode
updateUuids();//更新UUID
setBluetoothClassFromConfig();
mAdapterStateMachine.sendMessage(AdapterState.BREDR_STARTED);//通知AdapterState,隨即進入OnState;BT啓動成功
}
break;
......
}
mRegisteredProfiles、mRunningProfiles最終會跟config聲明的Profile一致,然後繼續做一些設置工作,其中我們可能比較關心的就是設置當前藍牙的工作模式了:
void onBluetoothReady() {
debugLog("onBluetoothReady, state=" + BluetoothAdapter.nameForState(getState())
+ ", ScanMode=" + mScanMode);
synchronized (mObject) {
// Reset adapter and profile connection states
setConnectionState(BluetoothAdapter.STATE_DISCONNECTED);
mProfileConnectionState.clear();
mProfilesConnected = 0;
mProfilesConnecting = 0;
mProfilesDisconnecting = 0;
// adapterPropertyChangedCallback has already been received. Set the scan mode.
setScanMode(AbstractionLayer.BT_SCAN_MODE_CONNECTABLE);//當前設備可以掃描和連接其他設備,其他設備無法掃描到當前設備
// This keeps NV up-to date on first-boot after flash.
setDiscoverableTimeout(mDiscoverableTimeout);//設置掃描的超時時長
}
}
我們可以在這裏設置希望的藍牙工作模式和掃描超時時長,這樣藍牙的啓動工作就基本結束了。