Bluetooth initialization - enable in Bluetooth process - Framework(Java)

1. Bluetooth Enable Overview

1.1 Bluetooth Enable Entrance

packages/apps/Bluetooth/src/com/android/bluetooth/btservice/AdapterService.java

    public static class AdapterServiceBinder extends IBluetooth.Stub {
        @Override
        public boolean enable(boolean quietMode) {
            AdapterService service = getService();
......
            return service.enable(quietMode);
        }
    }



    public synchronized boolean enable(boolean quietMode) {
......
        mQuietmode = quietMode;     // 由上層傳遞诅迷,測(cè)試設(shè)備的值 false
        mAdapterStateMachine.sendMessage(AdapterState.BLE_TURN_ON);
        return true;
    }

1.2 Bluetooth StateMachine Overview

packages/apps/Bluetooth/src/com/android/bluetooth/btservice/AdapterState.java
根據(jù)源碼注釋可知,藍(lán)牙開啟的狀態(tài)轉(zhuǎn)換關(guān)系如下圖:

藍(lán)牙啟動(dòng)的狀態(tài)機(jī)轉(zhuǎn)換圖.png

由上圖可知,經(jīng)歷 Off、TurningBleOn贺归、BleOn蕾殴、TurningOn、On 共五個(gè)狀態(tài)脑沿,藍(lán)牙處于完全的開啟狀態(tài)捉兴。
五個(gè)狀態(tài)中蝎困,僅僅 TurningBleOn 和 TurningOn 是不穩(wěn)定狀態(tài),無論操作成功與否都需要恢復(fù)到穩(wěn)定狀態(tài) Off倍啥、BleOn禾乘、On 三種狀態(tài)中的一種。

下面開始分析藍(lán)牙 enable 整體流程虽缕,分為 TurningBleOn 和 TurningOn 兩個(gè)流程分析盖袭。
首先整體介紹 enable 流程中狀態(tài)機(jī)的轉(zhuǎn)化,再分析 TurningBleOn彼宠,最后分析 TurningOn。

packages/apps/Bluetooth/src/com/android/bluetooth/btservice/AdapterState.java

final class AdapterState extends StateMachine {

    // 所有狀態(tài)的基類
    private abstract class BaseAdapterState extends State {

        abstract int getStateValue();

        // 進(jìn)入所有的具體狀態(tài)時(shí)弟塞,需要更新狀態(tài)信息凭峡。(若子類未重寫)
        @Override
        public void enter() {
            int currState = getStateValue();
            mAdapterService.updateAdapterState(mPrevState, currState);     // 0
            mPrevState = currState;
        }
......
    }


    private class OffState extends BaseAdapterState {
        @Override
        public boolean processMessage(Message msg) {
            switch (msg.what) {
                case BLE_TURN_ON:
                    transitionTo(mTurningBleOnState);        // 1
                    break;
            }
            return true;
        }
    }



    private class TurningBleOnState extends BaseAdapterState {

        @Override
        public void enter() {
            super.enter();
            sendMessageDelayed(BLE_START_TIMEOUT, BLE_START_TIMEOUT_DELAY);
            mAdapterService.bringUpBle();                  // 2
        }

        @Override
        public boolean processMessage(Message msg) {
            switch (msg.what) {
                case BLE_STARTED:
                    transitionTo(mBleOnState);             // 3
                    break;
......
            }
            return true;
        }
    }



    private class BleOnState extends BaseAdapterState {

        @Override
        public boolean processMessage(Message msg) {
            switch (msg.what) {
                case USER_TURN_ON:
                    transitionTo(mTurningOnState);        // 4
                    break;
......
            }
            return true;
        }
    }



    private class TurningOnState extends BaseAdapterState {

        @Override
        public void enter() {
            super.enter();
            sendMessageDelayed(BREDR_START_TIMEOUT, BREDR_START_TIMEOUT_DELAY);
            mAdapterService.startProfileServices();      // 5
        }

        @Override
        public boolean processMessage(Message msg) {
            switch (msg.what) {
                case BREDR_STARTED:
                    transitionTo(mOnState);              // 6
                    break;
......
            }
            return true;
        }
    }


    private class OnState extends BaseAdapterState {

        @Override
        public boolean processMessage(Message msg) {
            switch (msg.what) {
                case USER_TURN_OFF:
                    transitionTo(mTurningOffState);
                    break;

            }
            return true;
        }
    }
}

從以上 0~6 共計(jì) 7 個(gè)數(shù)字注釋可知,除了狀態(tài)轉(zhuǎn)移决记,狀態(tài)機(jī)主要執(zhí)行三個(gè)方法:

  1. mAdapterService.updateAdapterState(mPrevState, currState); 【//0摧冀,通用方法】
  2. mAdapterService.bringUpBle(); 【//2, TurningBleOn】
  3. mAdapterService.startProfileServices(); 【// 5系宫,TurningOn】

狀態(tài)機(jī)的狀態(tài)流轉(zhuǎn)過程中會(huì)先后執(zhí)行 bringUpBle() 和 startProfileServices()索昂,但此處還沒有涉及到這些方法是如何被觸發(fā)的,后續(xù)需要將這些內(nèi)容連貫起來扩借。

updateAdapterState() 方法是狀態(tài)機(jī)的通用方法椒惨。先分析其處理流程,再分析狀態(tài)機(jī)的狀態(tài)變化流程潮罪。

2. Bluetooth StateMachine State Update - updateAdapterState()

packages/apps/Bluetooth/src/com/android/bluetooth/btservice/AdapterService.java

    void updateAdapterState(int prevState, int newState) {
        mAdapterProperties.setState(newState);
        invalidateBluetoothGetStateCache();
        if (mCallbacks != null) {
            int n = mCallbacks.beginBroadcast();
            for (int i = 0; i < n; i++) {
                try {
                    mCallbacks.getBroadcastItem(i).onBluetoothStateChange(prevState, newState);
                } catch (RemoteException 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.get(BLUETOOTH_BTSNOOP_LOG_MODE_PROPERTY, "empty");
            mDefaultSnoopLogSettingAtEnable =
                    Settings.Global.getString(getContentResolver(),
                            Settings.Global.BLUETOOTH_BTSNOOP_DEFAULT_MODE);
            SystemProperties.set(BLUETOOTH_BTSNOOP_DEFAULT_MODE_PROPERTY,
                    mDefaultSnoopLogSettingAtEnable);
        } else if (newState == BluetoothAdapter.STATE_BLE_ON
                   && prevState != BluetoothAdapter.STATE_OFF) {
            String snoopLogSetting =
                    SystemProperties.get(BLUETOOTH_BTSNOOP_LOG_MODE_PROPERTY, "empty");
            String snoopDefaultModeSetting =
                    Settings.Global.getString(getContentResolver(),
                            Settings.Global.BLUETOOTH_BTSNOOP_DEFAULT_MODE);

            if (!TextUtils.equals(mSnoopLogSettingAtEnable, snoopLogSetting)
                    || !TextUtils.equals(mDefaultSnoopLogSettingAtEnable,
                            snoopDefaultModeSetting)) {
                mAdapterStateMachine.sendMessage(AdapterState.BLE_TURN_OFF);
            }
        }
    }

3. bringUpBle

packages/apps/Bluetooth/src/com/android/bluetooth/btservice/AdapterService.java

    void bringUpBle() {

        if (getResources().getBoolean(
                R.bool.config_bluetooth_reload_supported_profiles_when_enabled)) {
            Config.init(getApplicationContext());
        }

        mRemoteDevices.reset();
        mAdapterProperties.init(mRemoteDevices);

        mBondStateMachine = BondStateMachine.make(this, mAdapterProperties, mRemoteDevices);

        mJniCallbacks.init(mBondStateMachine, mRemoteDevices);

        try {
            mBatteryStats.noteResetBleScan();
        } catch (RemoteException e) {
            Log.w(TAG, "RemoteException trying to send a reset to BatteryStats");
        }

        // 5 Start Gatt service
        setProfileServiceState(GattService.class, BluetoothAdapter.STATE_ON);
    }

3.1 RemoteDevices

3.2 AdapterProperties

3.3 BondStateMachine

3.4 JniCallbacks

3.5 GattService Initialization

GattService 初始化詳情:GattService Initialization
根據(jù) GattService 的基類初始化 ProfileService Initialization 的內(nèi)容可知康谆,Profile 啟動(dòng)之后领斥,在AdapterService 中會(huì)記錄狀態(tài)以及可能會(huì)觸發(fā)后續(xù)的 藍(lán)牙enable 流程。

packages/apps/Bluetooth/src/com/android/bluetooth/btservice/AdapterService.java

public class AdapterService extends Service {

        private void processProfileServiceStateChanged(ProfileService profile, int state) {
            switch (state) {
                case BluetoothAdapter.STATE_ON:
                    ......
                    if (GattService.class.getSimpleName().equals(profile.getName())) {
                        // 啟動(dòng) GATT service 時(shí)沃暗,走該分支月洛,繼續(xù)執(zhí)行 enable
                        enableNative();
                    } else if (mRegisteredProfiles.size() == Config.getSupportedProfiles().length
                            && mRegisteredProfiles.size() == mRunningProfiles.size()) {
                        // 所有支持的 profile service 啟動(dòng)后,走該分支
                        ......
                    }
                    break;
                    ......
            }
        }
    }
}

以上代碼內(nèi)容孽锥,不僅是 ProfileService 的通用流程嚼黔,還是藍(lán)牙enable的整體流程的內(nèi)容。

  1. 若 GattService 啟動(dòng)完成惜辑,則執(zhí)行 enableNative()唬涧,詳情:Bluetooth initialization - enable in Bluetooth process - Native(Cpp)
  2. 若所有支持的 profile 啟動(dòng)完成韵丑,則執(zhí)行另外一個(gè)分支爵卒,具體內(nèi)容在下文介紹。

4. startProfileServices

    void startProfileServices() {
        Class[] supportedProfileServices = Config.getSupportedProfiles();
        if (supportedProfileServices.length == 1 && GattService.class.getSimpleName()
                .equals(supportedProfileServices[0].getSimpleName())) {
             ...... // 設(shè)備只支持 BLE 時(shí)走這里撵彻,不分析此路徑
        } else {
            setAllProfileServiceStates(supportedProfileServices, BluetoothAdapter.STATE_ON);
        }
    }
    private void setAllProfileServiceStates(Class[] services, int state) {
        for (Class service : services) {
            if (GattService.class.getSimpleName().equals(service.getSimpleName())) {
                continue;  // GattService 已經(jīng)初始化過了钓株,排除之
            }
            setProfileServiceState(service, state);
        }
    }
01-15 21:33:43.404 31081 31081 V AdapterServiceConfig: Adding HeadsetService
01-15 21:33:43.404 31081 31081 V AdapterServiceConfig: Adding A2dpService
01-15 21:33:43.404 31081 31081 V AdapterServiceConfig: Adding HidHostService
01-15 21:33:43.404 31081 31081 V AdapterServiceConfig: Adding PanService
01-15 21:33:43.404 31081 31081 V AdapterServiceConfig: Adding GattService
01-15 21:33:43.404 31081 31081 V AdapterServiceConfig: Adding BluetoothMapService
01-15 21:33:43.404 31081 31081 V AdapterServiceConfig: Adding AvrcpTargetService
01-15 21:33:43.404 31081 31081 V AdapterServiceConfig: Adding SapService
01-15 21:33:43.404 31081 31081 V AdapterServiceConfig: Adding HidDeviceService
01-15 21:33:43.404 31081 31081 V AdapterServiceConfig: Adding BluetoothOppService
01-15 21:33:43.404 31081 31081 V AdapterServiceConfig: Adding BluetoothPbapService
01-15 21:33:43.404 31081 31081 V AdapterServiceConfig: Adding HearingAidService 

Android 11 Pixel5 在藍(lán)牙進(jìn)程初始化時(shí)會(huì)添加以上這些Service,此處會(huì)分別初始化它們(除 GattService之外陌僵,GattService 在 bingUpBle 階段初始化)轴合。
Profiles 的初始化過程如下:
Profile Initialization - HeadsetService
Profile Initialization - A2dpService
Profile Initialization - HidHostService
Profile Initialization - HidDeviceService
Profile Initialization - PanService
Profile Initialization - SapService
Profile Initialization - AvrcpTargetService
Profile Initialization - BluetoothMapService
Profile Initialization - BluetoothPbapService
Profile Initialization - BluetoothOppService
Profile Initialization - HearingAidService

當(dāng)所有支持的 Profile 全部注冊(cè)并啟動(dòng)之后,執(zhí)行
packages/apps/Bluetooth/src/com/android/bluetooth/btservice/AdapterService.java

public class AdapterService extends Service {

        private void processProfileServiceStateChanged(ProfileService profile, int state) {
            switch (state) {
                case BluetoothAdapter.STATE_ON:
                    ......
                    if (GattService.class.getSimpleName().equals(profile.getName())) {
                        // 啟動(dòng) GATT service 時(shí)碗短,走該分支受葛,繼續(xù)執(zhí)行 enable
                        ......
                    } else if (mRegisteredProfiles.size() == Config.getSupportedProfiles().length
                            && mRegisteredProfiles.size() == mRunningProfiles.size()) {
                        // 所有支持的 profile service 啟動(dòng)后,走該分支
                        mAdapterProperties.onBluetoothReady();
                        updateUuids();
                        setBluetoothClassFromConfig();
                        initProfileServices();
                        getAdapterPropertyNative(AbstractionLayer.BT_PROPERTY_LOCAL_IO_CAPS);
                        getAdapterPropertyNative(AbstractionLayer.BT_PROPERTY_LOCAL_IO_CAPS_BLE);
                        mAdapterStateMachine.sendMessage(AdapterState.BREDR_STARTED);
                    }
                    break;
                    ......
            }
        }
    }
}

若所有支持的 profile 啟動(dòng)完成偎谁,則執(zhí)行一些其他的初始化操作总滩。
隨后向狀態(tài)機(jī)發(fā)送 BREDR_STARTED 消息,狀態(tài)機(jī)進(jìn)入 OnState巡雨。

5. Summary

經(jīng)過以上分析闰渔,藍(lán)牙初始化整體架構(gòu)如下圖:


Android Bluetooth Enable Arch
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市铐望,隨后出現(xiàn)的幾起案子冈涧,更是在濱河造成了極大的恐慌,老刑警劉巖正蛙,帶你破解...
    沈念sama閱讀 221,695評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件督弓,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡乒验,警方通過查閱死者的電腦和手機(jī)愚隧,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來锻全,“玉大人奸攻,你說我怎么就攤上這事蒜危。” “怎么了睹耐?”我有些...
    開封第一講書人閱讀 168,130評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵辐赞,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我硝训,道長(zhǎng)响委,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,648評(píng)論 1 297
  • 正文 為了忘掉前任窖梁,我火速辦了婚禮赘风,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘纵刘。我一直安慰自己邀窃,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,655評(píng)論 6 397
  • 文/花漫 我一把揭開白布假哎。 她就那樣靜靜地躺著瞬捕,像睡著了一般。 火紅的嫁衣襯著肌膚如雪舵抹。 梳的紋絲不亂的頭發(fā)上肪虎,一...
    開封第一講書人閱讀 52,268評(píng)論 1 309
  • 那天,我揣著相機(jī)與錄音惧蛹,去河邊找鬼扇救。 笑死,一個(gè)胖子當(dāng)著我的面吹牛香嗓,可吹牛的內(nèi)容都是我干的迅腔。 我是一名探鬼主播,決...
    沈念sama閱讀 40,835評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼靠娱,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼钾挟!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起饱岸,我...
    開封第一講書人閱讀 39,740評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎徽千,沒想到半個(gè)月后苫费,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,286評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡双抽,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,375評(píng)論 3 340
  • 正文 我和宋清朗相戀三年百框,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片牍汹。...
    茶點(diǎn)故事閱讀 40,505評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡铐维,死狀恐怖柬泽,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情嫁蛇,我是刑警寧澤锨并,帶...
    沈念sama閱讀 36,185評(píng)論 5 350
  • 正文 年R本政府宣布,位于F島的核電站睬棚,受9級(jí)特大地震影響第煮,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜抑党,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,873評(píng)論 3 333
  • 文/蒙蒙 一包警、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧底靠,春花似錦害晦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,357評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至痒芝,卻和暖如春俐筋,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背严衬。 一陣腳步聲響...
    開封第一講書人閱讀 33,466評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工澄者, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人请琳。 一個(gè)月前我還...
    沈念sama閱讀 48,921評(píng)論 3 376
  • 正文 我出身青樓粱挡,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親俄精。 傳聞我的和親對(duì)象是個(gè)殘疾皇子询筏,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,515評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容