Bluetooth initialization - enable in Settings & System_server process

1. Overview

Bluetooth.png

藍牙初始化框圖如上:

  1. 藍牙處于關(guān)閉狀態(tài)時袋狞,進程 com.android.bluetooth 不存在佛致。
  2. 以設(shè)置打開藍牙為例晌柬,藍牙初始化(即 enable)的流程是 com.android.settings(設(shè)置進程) ----> system_server(系統(tǒng)服務(wù)進程)----> com.android.bluetooth(藍牙進程
  3. 藍牙進程啟動之后识埋,設(shè)置應(yīng)用將直接與藍牙進程通信咪笑,無需再經(jīng)過系統(tǒng)服務(wù)進程浸剩。

2. Settings Process - 觸發(fā)開啟藍牙

frameworks/base/core/java/android/bluetooth/BluetoothAdapter.java

    public boolean enable() {
......
        try {
            return mManagerService.enable(ActivityThread.currentPackageName());
        } catch (RemoteException e) {
            Log.e(TAG, "", e);
        }
        return false;
    }

3. System_server Process

3.1 啟動藍牙進程

frameworks/base/services/core/java/com/android/server/BluetoothManagerService.java

    public boolean enable(String packageName) throws RemoteException {
......
        synchronized (mReceiver) {
......
            sendEnableMsg(false,
                    BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST, packageName);
        }
        return true;
    }

此處傳遞的 quietMode = false钾军;

    private void sendEnableMsg(boolean quietMode, int reason, String packageName) {
        mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_ENABLE, quietMode ? 1 : 0, 0));
......
    }
    private class BluetoothHandler extends Handler {
......
        @Override
        public void handleMessage(Message msg) {
                case MESSAGE_ENABLE:
......
                    mQuietEnable = (msg.arg1 == 1);  // mQuietEnable = false;
                    if (mBluetooth == null) {
                        handleEnable(mQuietEnable);
                    } 
......
                    break;

首次開啟時,由于 com.android.bluetooth 還未啟動绢要,因此 mBluetooth == null吏恭,故會執(zhí)行綁定服務(wù)的操作。

    private void handleEnable(boolean quietMode) {
        mQuietEnable = quietMode; // false

        try {
            if ((mBluetooth == null) && (!mBinding)) {
......
                Intent i = new Intent(IBluetooth.class.getName());
                if (!doBind(i, mConnection, 
                        Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT,
                        UserHandle.CURRENT)) {
                } else {
                    mBinding = true;
                }
            } else if (mBluetooth != null) {
......
            }
        }
    }
    boolean doBind(Intent intent, ServiceConnection conn, int flags, UserHandle user) {
        ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
        intent.setComponent(comp);
        if (comp == null || !mContext.bindServiceAsUser(intent, conn, flags, user)) {
            return false;
        }
        return true;
    }

綁定的是 IBluetooth 這個服務(wù)重罪,由以下配置信息可知樱哼,綁定的是 AdapterService.java哀九,該綁定過程會啟動 com.android.bluetooth 進程。
packages/apps/Bluetooth/AndroidManifest.xml

        <service android:process="@string/process"
             android:name=".btservice.AdapterService"
             android:exported="true">
            <intent-filter>
                <action android:name="android.bluetooth.IBluetooth"/>
            </intent-filter>
        </service>

藍牙進程的啟動過程由 藍牙進程初始化 來分析唇礁,此文繼續(xù)分析服務(wù)被綁定成功后的回調(diào)勾栗。

3.2 綁定 AdapterService 成功后的回調(diào)

frameworks/base/services/core/java/com/android/server/BluetoothManagerService.java

    private class BluetoothServiceConnection implements ServiceConnection {
        public void onServiceConnected(ComponentName componentName, IBinder service) {
            String name = componentName.getClassName();

            Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_CONNECTED);
            if (name.equals("com.android.bluetooth.btservice.AdapterService")) {
                msg.arg1 = SERVICE_IBLUETOOTH;
......
            }
            msg.obj = service;
            mHandler.sendMessage(msg);
        }
......
    }



    private BluetoothServiceConnection mConnection = new BluetoothServiceConnection();

以上源碼主要是創(chuàng)建了 MESSAGE_BLUETOOTH_SERVICE_CONNECTED 消息,下面開始處理該消息盏筐。

    private class BluetoothHandler extends Handler {
......
        @Override
        public void handleMessage(Message msg) {
                case MESSAGE_BLUETOOTH_SERVICE_CONNECTED: {

                    IBinder service = (IBinder) msg.obj;
                    try {
                        mBluetoothLock.writeLock().lock();
                        if (msg.arg1 == SERVICE_IBLUETOOTHGATT) {
......
                            return;
                        } // else must be SERVICE_IBLUETOOTH
......
                        mBinding = false;
                        mBluetoothBinder = service;
                        // 0. 獲取藍牙進程藍牙適配器服務(wù)的代理對象
                        mBluetooth = IBluetooth.Stub.asInterface(Binder.allowBlocking(service));
......
                        // 1. 向藍牙進程注冊回調(diào)函數(shù)围俘,以達到雙向通信的目的
                        try {
                            mBluetooth.registerCallback(mBluetoothCallback);
                        } catch (RemoteException re) {
                            Slog.e(TAG, "Unable to register BluetoothCallback", re);
                        }
                        // 2. Inform BluetoothAdapter instances that service is up
                        sendBluetoothServiceUpCallback();

                        // 3. Do enable request
                        try {
                            if (!mBluetooth.enable(mQuietEnable)) {
                                Slog.e(TAG, "IBluetooth.enable() returned false");
                            }
                        } catch (RemoteException e) {
                            Slog.e(TAG, "Unable to call enable()", e);
                        }

處理 MESSAGE_BLUETOOTH_SERVICE_CONNECTED 消息,從源碼可知:
首先琢融,獲取并保存藍牙進程入口的代理對象:mBluetooth界牡;
其次,

  1. 向藍牙進程注冊回調(diào)漾抬,用于藍牙進程向系統(tǒng)服務(wù)進程發(fā)送消息宿亡;
  2. 執(zhí)行應(yīng)用層注冊到系統(tǒng)服務(wù)進程的回調(diào),向已注冊的應(yīng)用進程提供 藍牙進程入口的代理對象纳令;
  3. 向藍牙進程發(fā)起執(zhí)行 enable 操作的請求挽荠。

3.2.1 registerCallback

3.2.1.1 Register Flow

packages/apps/Bluetooth/src/com/android/bluetooth/btservice/AdapterService.java
AdapterService 存儲該回調(diào)對象,在合適的時候觸發(fā)回調(diào)平绩。

public class AdapterService extends Service {

    private RemoteCallbackList<IBluetoothCallback> mCallbacks = 
            new RemoteCallbackList<IBluetoothCallback>();

    public static class AdapterServiceBinder extends IBluetooth.Stub {

        public void registerCallback(IBluetoothCallback callback) {
            AdapterService service = getService();
......
            service.mCallbacks.register(callback);
        }
    }

3.2.1.2 Callback Implementation

frameworks/base/services/core/java/com/android/server/BluetoothManagerService.java

    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);
            mHandler.sendMessage(msg);
        }
    };

從以上源碼可知圈匆,藍牙進程調(diào)用該回調(diào)以通知系統(tǒng)服務(wù)進程藍牙的狀態(tài)變化信息。

    private class BluetoothHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MESSAGE_BLUETOOTH_STATE_CHANGE: {
                    int prevState = msg.arg1;
                    int newState = msg.arg2;
                    mState = newState;
                    bluetoothStateChangeHandler(prevState, newState);
  ......
                    break;
                }

bluetoothStateChangeHandler() 負責(zé)更新狀態(tài)捏雌,并發(fā)送狀態(tài)變化的廣播跃赚。

3.2.1.3 Callback Invoke Example

回調(diào)方法執(zhí)行的源碼如下
packages/apps/Bluetooth/src/com/android/bluetooth/btservice/AdapterService.java

    void updateAdapterState(int prevState, int newState) {
......
        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();
        }

frameworks/base/core/java/android/os/RemoteCallbackList.java

public class RemoteCallbackList<E extends IInterface> {

    public int beginBroadcast() {
        synchronized (mCallbacks) {         
            final int N = mBroadcastCount = mCallbacks.size();
            if (N <= 0) {
                return 0;
            }
            Object[] active = mActiveBroadcast;
            if (active == null || active.length < N) {
                mActiveBroadcast = active = new Object[N];
            }
            for (int i=0; i<N; i++) {
                active[i] = mCallbacks.valueAt(i);
            }
            return N;
        }
    }

    public void finishBroadcast() {
        synchronized (mCallbacks) {
            Object[] active = mActiveBroadcast;
            if (active != null) {
                final int N = mBroadcastCount;
                for (int i=0; i<N; i++) {
                    active[i] = null;
                }
            }
            mBroadcastCount = -1;
        }
    }
}

3.2.2 sendBluetoothServiceUpCallback

frameworks/base/services/core/java/com/android/server/BluetoothManagerService.java

    private final RemoteCallbackList<IBluetoothManagerCallback> mCallbacks = 
            new RemoteCallbackList<IBluetoothManagerCallback>();;

    private void sendBluetoothServiceUpCallback() {
        synchronized (mCallbacks) {
            try {
                int n = mCallbacks.beginBroadcast();
                for (int i = 0; i < n; i++) {
                    try {
                        mCallbacks.getBroadcastItem(i).onBluetoothServiceUp(mBluetooth);
                    } catch (RemoteException e) {
                        Slog.e(TAG, "Unable to call onBluetoothServiceUp() on callback #" + i, e);
                    }
                }
            } finally {
                mCallbacks.finishBroadcast();
            }
        }
    }

BluetoothManagerService 回調(diào)應(yīng)用層注冊的回調(diào)對象的方法 onBluetoothServiceUp(),將藍牙進程入口的代理對象發(fā)送到該應(yīng)用性湿。

frameworks/base/core/java/android/bluetooth/BluetoothDevice.java

public final class BluetoothDevice implements Parcelable {

    static IBluetoothManagerCallback sStateChangeCallback = new IBluetoothManagerCallback.Stub() {

        public void onBluetoothServiceUp(IBluetooth bluetoothService)
                throws RemoteException {
            synchronized (BluetoothDevice.class) {
                if (sService == null) {
                    sService = bluetoothService;
                }
            }
        }
        ......
    }
}

3.2.3 Bluetooth Process enable

藍牙進程繼續(xù)執(zhí)行 enable 操作的內(nèi)容較多纬傲,鏈接如下。
Bluetooth initialization - enable in Bluetooth process

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末肤频,一起剝皮案震驚了整個濱河市叹括,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌宵荒,老刑警劉巖领猾,帶你破解...
    沈念sama閱讀 216,997評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異骇扇,居然都是意外死亡,警方通過查閱死者的電腦和手機面粮,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,603評論 3 392
  • 文/潘曉璐 我一進店門少孝,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人熬苍,你說我怎么就攤上這事稍走≡蹋” “怎么了?”我有些...
    開封第一講書人閱讀 163,359評論 0 353
  • 文/不壞的土叔 我叫張陵婿脸,是天一觀的道長粱胜。 經(jīng)常有香客問我,道長狐树,這世上最難降的妖魔是什么焙压? 我笑而不...
    開封第一講書人閱讀 58,309評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮抑钟,結(jié)果婚禮上涯曲,老公的妹妹穿的比我還像新娘。我一直安慰自己在塔,他們只是感情好幻件,可當(dāng)我...
    茶點故事閱讀 67,346評論 6 390
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著蛔溃,像睡著了一般绰沥。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上贺待,一...
    開封第一講書人閱讀 51,258評論 1 300
  • 那天徽曲,我揣著相機與錄音,去河邊找鬼狠持。 笑死疟位,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的喘垂。 我是一名探鬼主播甜刻,決...
    沈念sama閱讀 40,122評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼正勒!你這毒婦竟也來了得院?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,970評論 0 275
  • 序言:老撾萬榮一對情侶失蹤章贞,失蹤者是張志新(化名)和其女友劉穎祥绞,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體鸭限,經(jīng)...
    沈念sama閱讀 45,403評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡蜕径,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,596評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了败京。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片兜喻。...
    茶點故事閱讀 39,769評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖赡麦,靈堂內(nèi)的尸體忽然破棺而出朴皆,到底是詐尸還是另有隱情帕识,我是刑警寧澤,帶...
    沈念sama閱讀 35,464評論 5 344
  • 正文 年R本政府宣布遂铡,位于F島的核電站肮疗,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏扒接。R本人自食惡果不足惜伪货,卻給世界環(huán)境...
    茶點故事閱讀 41,075評論 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望珠增。 院中可真熱鬧超歌,春花似錦、人聲如沸蒂教。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,705評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽凝垛。三九已至懊悯,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間梦皮,已是汗流浹背炭分。 一陣腳步聲響...
    開封第一講書人閱讀 32,848評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留剑肯,地道東北人捧毛。 一個月前我還...
    沈念sama閱讀 47,831評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像让网,于是被迫代替她去往敵國和親呀忧。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,678評論 2 354

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

  • 1 基礎(chǔ)知識介紹 1.1 縮略語 BTIF: Bluetooth Interface BTU: Bluetooth...
    vivian310閱讀 2,183評論 0 1
  • 1:InputChannel提供函數(shù)創(chuàng)建底層的Pipe對象 2: 1)客戶端需要新建窗口 2)new ViewRo...
    自由人是工程師閱讀 5,301評論 0 18
  • 正在開發(fā)中的系統(tǒng)基礎(chǔ)平臺由安卓10升級到了安卓11溃睹,美工提供的好好的壁紙圖竟然悄無聲息的被放大了而账,大概是這樣: 美...
    鵜鶘醍醐閱讀 4,343評論 0 6
  • 一、前言 本文側(cè)重點:Android中藍牙代碼結(jié)構(gòu)分析因篇。代碼來源于Android P泞辐,本文相關(guān)代碼:client:...
    Yink_Liu閱讀 12,279評論 0 10
  • 0. Overview 藍牙模塊出現(xiàn)多種類型的Log: ALOGV(....); LOG_<log_level>,...
    MelanDawn閱讀 1,902評論 0 0