剛刷完機,藍牙打不開

先要了解機器的啓動流程:
機器啓動
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的日誌

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章