先要了解機器的啓動流程:
機器啓動
SystemServer進程會啓動BluetoothService,在
BluetoothService裏會拉起BluetoothManagerService BluetoothManagerService
在藍牙打開時會去綁定AdapterService(藍牙服務APK),綁定成功的話AMS針對mConnection
會執行回調函數即 onServiceConnected在這裏就會註冊 IBluetoothCallback
到AdapterService,用於接收藍牙stack的狀態(Adapter state)更新,本CR就是因爲
這個IBluetoothCallback沒有註冊到AdapterService所以,收不到狀態更新,UI上看不到藍牙ON。
關鍵日誌:
01-04 00:02:38.769 2166 2310 D BluetoothAdapterService: updateAdapterState() - Broadcasting state to 0 receivers.
調用流程:
frameworks/base/services/java/com/android/server/SystemServer.java
#startOtherServices
// support Bluetooth - see bug 988521
if (isEmulator) {
Slog.i(TAG, "No Bluetooth Service (emulator)");
} else if (mFactoryTestMode == FactoryTest.FACTORY_TEST_LOW_LEVEL) {
Slog.i(TAG, "No Bluetooth Service (factory test)");
} else if (!context.getPackageManager().hasSystemFeature
(PackageManager.FEATURE_BLUETOOTH)) {
Slog.i(TAG, "No Bluetooth Service (Bluetooth Hardware Not Present)");
} else if (disableBluetooth) {
Slog.i(TAG, "Bluetooth Service disabled by config");
} else {
traceBeginAndSlog("StartBluetoothService");
mSystemServiceManager.startService(BluetoothService.class);
traceEnd();
}
frameworks/base/services/core/java/com/android/server/BluetoothService
#onBootPhase
@Override
public void onBootPhase(int phase) {
if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
publishBinderService(BluetoothAdapter.BLUETOOTH_MANAGER_SERVICE,
mBluetoothManagerService);
// M: ALPS02790269: delay boot phase for hci log storage
} else if (phase == SystemService.PHASE_BOOT_COMPLETED) {
mBluetoothManagerService.handleOnBootPhase();
}
}
frameworks/base/services/core/java/com/android/server/BluetoothManagerService
綁定AdapterService
private void handleEnable(boolean quietMode) {
mQuietEnable = quietMode;
try {
mBluetoothLock.writeLock().lock();
if ((mBluetooth == null) && (!mBinding)) {
//Start bind timeout and bind
Message timeoutMsg=mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND);
mHandler.sendMessageDelayed(timeoutMsg,TIMEOUT_BIND_MS);
Intent i = new Intent(IBluetooth.class.getName());
if (!doBind(i, mConnection,Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT,
UserHandle.CURRENT)) {
mHandler.removeMessages(MESSAGE_TIMEOUT_BIND);
} else {
mBinding = true;
}
} else if (mBluetooth != null) {
//Enable bluetooth
try {
if (!mQuietEnable) {
if(!mBluetooth.enable()) {
Slog.e(TAG,"IBluetooth.enable() returned false");
}
}
else {
if(!mBluetooth.enableNoAutoConnect()) {
Slog.e(TAG,"IBluetooth.enableNoAutoConnect() returned false");
}
}
} catch (RemoteException e) {
Slog.e(TAG,"Unable to call enable()",e);
}
}
} finally {
mBluetoothLock.writeLock().unlock();
}
AMS回調:
private class BluetoothServiceConnection implements ServiceConnection {
public void onServiceConnected(ComponentName componentName, IBinder service) {
String name = componentName.getClassName();
if (DBG) Slog.d(TAG, "BluetoothServiceConnection: " + name);
Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_CONNECTED);
if (name.equals("com.android.bluetooth.btservice.AdapterService")) {
msg.arg1 = SERVICE_IBLUETOOTH;
} else if (name.equals("com.android.bluetooth.gatt.GattService")) {
msg.arg1 = SERVICE_IBLUETOOTHGATT;
} else {
Slog.e(TAG, "Unknown service connected: " + name);
return;
}
msg.obj = service;
mHandler.sendMessage(msg);
}
public void onServiceDisconnected(ComponentName componentName) {
// Called if we unexpectedly disconnect.
String name = componentName.getClassName();
if (DBG) Slog.d(TAG, "BluetoothServiceConnection, disconnected: " + name);
Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED);
if (name.equals("com.android.bluetooth.btservice.AdapterService")) {
msg.arg1 = SERVICE_IBLUETOOTH;
} else if (name.equals("com.android.bluetooth.gatt.GattService")) {
msg.arg1 = SERVICE_IBLUETOOTHGATT;
} else {
Slog.e(TAG, "Unknown service disconnected: " + name);
return;
}
mHandler.sendMessage(msg);
}
}
handle Message處理MESSAGE_BLUETOOTH_SERVICE_CONNECTED
case MESSAGE_BLUETOOTH_SERVICE_CONNECTED:
{
if (DBG) Slog.d(TAG,"MESSAGE_BLUETOOTH_SERVICE_CONNECTED: " + msg.arg1);
IBinder service = (IBinder) msg.obj;
try {
mBluetoothLock.writeLock().lock();
if (msg.arg1 == SERVICE_IBLUETOOTHGATT) {
mBluetoothGatt = IBluetoothGatt.Stub
.asInterface(Binder.allowBlocking(service));
onBluetoothGattServiceUp();
break;
} // else must be SERVICE_IBLUETOOTH
//Remove timeout
mHandler.removeMessages(MESSAGE_TIMEOUT_BIND);
mBinding = false;
mBluetoothBinder = service;
mBluetooth = IBluetooth.Stub.asInterface(Binder.allowBlocking(service));
if (!isNameAndAddressSet()) {
Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS);
mHandler.sendMessage(getMsg);
if (mGetNameAddressOnly) return;
}
//Register callback object
try {
mBluetooth.registerCallback(mBluetoothCallback);
} catch (RemoteException re) {
Slog.e(TAG, "Unable to register BluetoothCallback",re);
}
//Inform BluetoothAdapter instances that service is up
sendBluetoothServiceUpCallback();
//Do enable request
try {
check爲什麼沒有register Ibluetoothcall.
失敗的log:
01-04 00:01:23.152 853 865 E mmm: BMS registerAdapter mBluetooth====android.bluetooth.IBluetooth$Stub$Proxy@7702836
01-04 00:01:34.265 853 874 E mmm: framework bluetoothManagerService handleEnable mBluetooth====android.bluetooth.IBluetooth$Stub$Proxy@7702836 mBinding ==false
成功的log:
01-01 00:01:00.163 694 942 E mmm: BMS registerAdapter mBluetooth====null
01-01 00:01:28.313 694 778 E mmm: framework bluetoothManagerService handleEnable mBluetooth====null mBinding ==false
對比發現:通過標黃的發現mBluetooth 剛刷完機時有值的,並不是空的,所以不能走進下面的方法,導致失敗。
if ((mBluetooth == null) && (!mBinding)) {
//Start bind timeout and bind
Message timeoutMsg=mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND);
mHandler.sendMessageDelayed(timeoutMsg,TIMEOUT_BIND_MS);
Intent i = new Intent(IBluetooth.class.getName());
android.util.Log.e("muyuanyuan","framework bluetoothManagerService handleEnable i====="+i);
android.util.Log.e("muyuanyuan","framework bluetoothManagerService handleEnable====="+(!doBind(i, mConnection,Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT,
UserHandle.CURRENT)));
if (!doBind(i, mConnection,Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT,
UserHandle.CURRENT)) {
android.util.Log.e("muyuanyuan","framework bluetoothManagerService handleEnable mConnection====="+mConnection);
mHandler.removeMessages(MESSAGE_TIMEOUT_BIND);
} else {
mBinding = true;
}
}
在以下方法中,mBluetooth剛開始是空的,但是由於回調又有值了:
public IBluetooth registerAdapter(IBluetoothManagerCallback callback){
if (callback == null) {
Slog.w(TAG, "Callback is null in registerAdapter");
return null;
}
Message msg = mHandler.obtainMessage(MESSAGE_REGISTER_ADAPTER);
msg.obj = callback;
mHandler.sendMessageAtFrontOfQueue(msg);
try {
mBluetoothLock.writeLock().lock();
android.util.Log.e("mmm","BMS registerAdapter mBluetooth===="+mBluetooth);
return mBluetooth;
} finally {
mBluetoothLock.writeLock().unlock();
}
}
失敗和成功的差異點在成功的時候有unbindAndFinish。
成功
01-01 00:00:13.369 704 776 D BluetoothManagerService: unbindAndFinish(): android.bluetooth.IBluetooth$Stub$Proxy@2807655 mBinding = false mUnbinding = false
通過unbindAndFinish()方法,跟蹤到以下方法:
case MESSAGE_SAVE_NAME_AND_ADDRESS: {
boolean unbind = false;
if (DBG) Slog.d(TAG,"MESSAGE_SAVE_NAME_AND_ADDRESS");
try {
mBluetoothLock.writeLock().lock();
if (!mEnable && mBluetooth != null) {
try {
// M: During the first bootup, enable BT to BleOn state
// and then get name and address
mBluetooth.enable();
} catch (RemoteException e) {
Slog.e(TAG,"Unable to call enable()",e);
}
}
} finally {
mBluetoothLock.writeLock().unlock();
}
if (mBluetooth != null) waitForBleOn(); // M: Wait for BleOn state
try {
mBluetoothLock.writeLock().lock();
try {
android.util.Log.e("mmm","BMS MESSAGE_SAVE_NAME_AND_ADDRESS mBluetooth === "+ mBluetooth + " mBluetooth.getName()==="+(mBluetooth.getName()));
} catch (RemoteException re) {
Slog.e("mmm","RemoteException====== ",re);
}
if (mBluetooth != null) {
String name = null;
String address = null;
try {
name = mBluetooth.getName();
address = mBluetooth.getAddress();
} catch (RemoteException re) {
Slog.e(TAG,"",re);
}
android.util.Log.e("mmm","BMS MESSAGE_SAVE_NAME_AND_ADDRESS name ====== "+name+" address======"+address+" mGetNameAddressOnly==== "+mGetNameAddressOnly);
if (name != null && address != null) {
storeNameAndAddress(name,address);
if (mGetNameAddressOnly) {
unbind = true;
}
} else {
android.util.Log.e("mmm","BMS msg.arg1 < MAX_SAVE_RETRIES "+(msg.arg1 < MAX_SAVE_RETRIES));
if (msg.arg1 < MAX_SAVE_RETRIES) {
Message retryMsg =
mHandler.obtainMessage(MESSAGE_SAVE_NAME_AND_ADDRESS);
retryMsg.arg1= 1+msg.arg1;
if (DBG) {
Slog.d(TAG,"Retrying name/address remote retrieval " +
"and save.....Retry count =" + retryMsg.arg1);
}
mHandler.sendMessageDelayed(retryMsg, TIMEOUT_SAVE_MS);
} else {
Slog.w(TAG,"Maximum name/address remote" +
"retrieval retry exceeded");
if (mGetNameAddressOnly) {
unbind = true;
}
}
}
if (!mEnable) {
try {
// M: Disable BT from BleOn state
mBluetooth.onBrEdrDown();
} catch (RemoteException e) {
Slog.e(TAG,"Unable to call disable()",e);
}
}
} else {
// rebind service by Request GET NAME AND ADDRESS
// if service is unbinded by disable or
// MESSAGE_BLUETOOTH_SERVICE_CONNECTED is not received
Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS);
mHandler.sendMessage(getMsg);
}
} finally {
mBluetoothLock.writeLock().unlock();
}
if (!mEnable && mBluetooth != null) {
waitForOnOff(false, true);
}
android.util.Log.e("mmm","BMS MESSAGE_SAVE_NAME_AND_ADDRESS unbind ====== "+unbind);
if (unbind) {
unbindAndFinish();
}
mGetNameAddressOnly = false;
break;
}
01-04 00:00:21.612 762 848 E mmm: BMS MESSAGE_SAVE_NAME_AND_ADDRESS name ====== null address======16:E4:46:00:00:74 mGetNameAddressOnly==== true
01-04 00:00:21.612 762 848 E mmm: BMS msg.arg1 < MAX_SAVE_RETRIES true
01-04 00:00:22.548 762 848 E mmm: BMS MESSAGE_SAVE_NAME_AND_ADDRESS unbind ====== false
01-04 00:00:23.611 762 848 E mmm: BMS MESSAGE_SAVE_NAME_AND_ADDRESS mBluetooth === android.bluetooth.IBluetooth$Stub$Proxy@3630ae6 mBluetooth.getName()===Oneida
01-04 00:00:23.627 762 848 E mmm: BMS MESSAGE_SAVE_NAME_AND_ADDRESS name ====== Oneida address======16:E4:46:00:00:74 mGetNameAddressOnly==== false
01-04 00:00:23.963 762 848 E mmm: BMS MESSAGE_SAVE_NAME_AND_ADDRESS unbind ====== false
過log可以看出,由於name第一次獲取的時候爲null,mGetNameAddressOnly爲true,所以導致unbind爲false,由於 (msg.arg1 < MAX_SAVE_RETRIES)= true,所以該case MESSAGE_SAVE_NAME_AND_ADDRESS 又走了一遍,這次name獲取到了值,但是mGetNameAddressOnly由於走了兩次,變成了fasle,所以unbind依然爲false,就一直不能走進去。
android.util.Log.e("mmm","BMS MESSAGE_SAVE_NAME_AND_ADDRESS unbind ====== "+unbind);
if (unbind) {
unbindAndFinish();
}
unbindAndFinish()
//該問題就是因爲name 獲取的比較遲,成功的是log,是一次就成功了
01-01 00:00:17.095 763 786 E mmm: BMS MESSAGE_SAVE_NAME_AND_ADDRESS name ====== HomePhone 4G address======DE:B4:46:00:00:33 mGetNameAddressOnly==== true
01-01 00:00:17.727 763 786 E mmm: BMS MESSAGE_SAVE_NAME_AND_ADDRESS unbind ====== true
failure log 裏看ble on 的狀態上報較慢,BIND_TIMEOUT異常,成功和失敗的日誌都會有出現,就是waitForBle timeout在失敗的日誌中出現,查看日誌看就是bt_stack_manager比較慢
回報狀態,check framework邏輯,這目前這種場景下 mGetNameAddressOnly必定會爲false,所以當處在save name重試狀態下直接等待ble on
狀態,而不需要check其他狀態,修改如下代碼:
if (name != null && address != null) {
storeNameAndAddress(name,address);
if (mGetNameAddressOnly) {
unbind = true;
}
} else {
if (msg.arg1 < MAX_SAVE_RETRIES) {
Message retryMsg =
mHandler.obtainMessage(MESSAGE_SAVE_NAME_AND_ADDRESS);
retryMsg.arg1= 1+msg.arg1;
if (DBG) {
Slog.d(TAG,"Retrying name/address remote retrieval " +
"and save.....Retry count =" + retryMsg.arg1);
}
mHandler.sendMessageDelayed(retryMsg, TIMEOUT_SAVE_MS);
break;
} else {
Slog.w(TAG,"Maximum name/address remote" +
"retrieval retry exceeded");
if (mGetNameAddressOnly) {
unbind = true;
}
}
}
補充:
藍牙默認值路徑
/frameworks/base/packages/SettingsProvider/res/values/
H A D defaults.xml 39 <bool name="def_bluetooth_on">true</bool>
BluetoothManagerService的log打印在sys_log中
在DOS中輸入
//清除日誌緩存
adb logcat -c
回車
//抓取日誌
輸入
adb logcat -v threadtime > D:\log.txt
回車,
開始測試,
測試結束
Ctrl+C
到D盤找到log.txt(此log不區分main sys log)分析即可。
調試建議
(1)刷完版本後,立馬在DOS中輸入抓取log的指令,wait for device,這樣才能抓取到SystemServer進程啓動BluetoothService的日誌