**版本:**Android 9 **平臺:**RK-PX30 問題描述:在狀態欄點擊藍牙圖標打開藍牙時,發現打開失敗,進入到設置里打開藍牙卻能打開成功,但是時間會比較長。 分析: 查看日誌發現,執行BluetoothHci::initialize()後,在獲取到藍牙MAC地址,就又把藍牙關閉了。測 ...
版本:Android 9
平臺:RK-PX30
問題描述:在狀態欄點擊藍牙圖標打開藍牙時,發現打開失敗,進入到設置里打開藍牙卻能打開成功,但是時間會比較長。
分析:
查看日誌發現,執行BluetoothHci::initialize()
後,在獲取到藍牙MAC地址,就又把藍牙關閉了。測試發現如果把藍牙開啟超時時間設置長點就可以正常打開了(由原本的4s改為10s)。
2021-10-27 14:32:30.561 495-522/system_process D/BluetoothManagerService: MESSAGE_BLUETOOTH_STATE_CHANGE: OFF > BLE_TURNING_ON
2021-10-27 14:32:30.561 495-522/system_process D/BluetoothManagerService: Sending BLE State Change: OFF > BLE_TURNING_ON
2021-10-27 14:32:30.561 19461-19482/com.android.bluetooth D/BluetoothAdapterService: bleOnProcessStart()
2021-10-27 14:32:30.564 19461-19482/com.android.bluetooth D/BluetoothAdapterService: bleOnProcessStart() - Make Bond State Machine
2021-10-27 14:32:30.565 19461-19482/com.android.bluetooth D/BluetoothBondStateMachine: make
2021-10-27 14:32:30.570 19461-19497/com.android.bluetooth I/BluetoothBondStateMachine: StableState(): Entering Off State
2021-10-27 14:32:30.595 19461-19461/com.android.bluetooth D/BluetoothAdapterService: getAdapterService() - returning com.android.bluetooth.btservice.AdapterService@e8fb3e7
2021-10-27 14:32:30.600 19461-19461/com.android.bluetooth D/BluetoothAdapterService: getAdapterService() - returning com.android.bluetooth.btservice.AdapterService@e8fb3e7
2021-10-27 14:32:30.613 19461-19461/com.android.bluetooth D/BluetoothAdapterService: getAdapterService() - returning com.android.bluetooth.btservice.AdapterService@e8fb3e7
2021-10-27 14:32:30.615 19461-19461/com.android.bluetooth D/BluetoothAdapterService: handleMessage() - Message: 2
2021-10-27 14:32:30.615 19461-19461/com.android.bluetooth D/BluetoothAdapterService: handleMessage() - MESSAGE_PROFILE_SERVICE_REGISTERED
2021-10-27 14:32:30.616 19461-19461/com.android.bluetooth D/BluetoothAdapterService: handleMessage() - Message: 1
2021-10-27 14:32:30.616 19461-19461/com.android.bluetooth D/BluetoothAdapterService: handleMessage() - MESSAGE_PROFILE_SERVICE_STATE_CHANGED
2021-10-27 14:32:30.628 19461-19502/com.android.bluetooth I/bt_hci: hci_initialize: IBluetoothHci::getService() returned 0x76f4876c60 (remote)
2021-10-27 14:32:30.628 260-260/? I/[email protected]: BluetoothHci::initialize() # 初始化
2021-10-27 14:32:34.566 19461-19482/com.android.bluetooth D/BluetoothAdapterService: updateAdapterState() - Broadcasting state BLE_TURNING_OFF to 1 receivers.
2021-10-27 14:32:34.567 495-522/system_process D/BluetoothManagerService: MESSAGE_BLUETOOTH_STATE_CHANGE: BLE_TURNING_ON > BLE_TURNING_OFF
2021-10-27 14:32:34.567 495-522/system_process D/BluetoothManagerService: Sending BLE State Change: BLE_TURNING_ON > BLE_TURNING_OFF # 從log的時間來看,過了大概4s就把藍牙狀態設置為關閉,代碼中超時時間就是4s
2021-10-27 14:32:34.742 495-495/system_process D/BluetoothManagerService: Bluetooth Adapter address changed to 0F:DD:CC:AA:EE:0A # 調用的initialize() 4s後才返回結果,但此時狀態已經設置為BLE_TURNING_OFF了
2021-10-27 14:32:34.743 495-495/system_process D/BluetoothManagerService: Stored Bluetoothaddress: 0F:DD:CC:AA:EE:0A
2021-10-27 14:32:34.744 495-495/system_process D/BluetoothManagerService: Bluetooth Adapter name changed to IPPhone
2021-10-27 14:32:34.747 495-495/system_process D/BluetoothManagerService: Stored Bluetooth name: IPPhone
2021-10-27 14:32:34.759 19461-19461/com.android.bluetooth D/BluetoothAdapterService: handleMessage() - Message: 1
2021-10-27 14:32:34.759 19461-19461/com.android.bluetooth D/BluetoothAdapterService: handleMessage() - MESSAGE_PROFILE_SERVICE_STATE_CHANGED
2021-10-27 14:32:34.760 19461-19461/com.android.bluetooth D/BluetoothAdapterService: handleMessage() - Message: 3
2021-10-27 14:32:34.760 19461-19461/com.android.bluetooth D/BluetoothAdapterService: handleMessage() - MESSAGE_PROFILE_SERVICE_UNREGISTERED
2021-10-27 14:32:34.761 19461-19482/com.android.bluetooth D/BluetoothAdapterService: updateAdapterState() - Broadcasting state OFF to 1 receivers.
2021-10-27 14:32:34.761 495-522/system_process D/BluetoothManagerService: MESSAGE_BLUETOOTH_STATE_CHANGE: BLE_TURNING_OFF > OFF
繼續分析,其他語言使用都正常,為什麼只有希臘語會有出現這種情況呢?
對比正常情況,BluetoothHci::initialize()
調用後在2s內就會返回結果,因此問題就在於希臘語下BluetoothHci::initialize()
的時間過長,這種問題最簡單的分析方法就是在可能有耗時較長的地方加log列印時間。
logcat本身會列印時間,如果是沒有列印時間的,就需要使用其他方式計算時間了。
最後定位到源碼里packages/apps/Bluetooth/src/com/android/bluetooth/Utils.java
的getAddressStringFromByte()
方法。
這個方法裡面很簡單,就只是調用了format()
方法,但是該方法卻卡了至少2~4s的時間,加上其他步驟本身就需要接近2s,而上層BLE開啟的超時時間是4s,因此很容易就導致超時而打不開。
繼續跟蹤format()
方法的實現:
format() # libcore/ojluni/src/main/java/java/util/Formatter.java
` toString()
` toUpperCase() # libcore/libart/src/main/java/java/lang/CaseMapper.java
最終找到根本原因是使用了希臘語的toUpperCase()
方法。
該方法實現如下:
public static String toUpperCase(Locale locale, String s, int count) {
String languageCode = locale.getLanguage();
if (languageCode.equals("tr") || languageCode.equals("az") || languageCode.equals("lt")) {
return ICU.toUpperCase(s, locale);
}
if (languageCode.equals("el")) { // 希臘語使用特殊方法處理
return EL_UPPER.get().transliterate(s);
}
}
private static final ThreadLocal<Transliterator> EL_UPPER = new ThreadLocal<Transliterator>() {
@Override protected Transliterator initialValue() {
return Transliterator.getInstance("el-Upper");
}
};
android使用開源轉換庫icu做處理,在調用希臘語轉換模塊的時候需要生成大量的對象,因此第一次調用會有很明顯的延遲。
經過驗證,如果對toUpperCase()
指定其他語言,也不會存在延遲;並且其他APP第一次調用該方法,也會有延遲。
解決方案:我們的解決方案是提前創建該對象,使用的時候就不會有延遲了。