Bluetooth initialization - enable in Settings & System_server process

1. Overview

Bluetooth.png

蓝牙初始化框图如上:

  1. 蓝牙处于关闭状态时,进程 com.android.bluetooth 不存在。
  2. 以设置打开蓝牙为例,蓝牙初始化(即 enable)的流程是 com.android.settings(设置进程) ----> system_server(系统服务进程)----> com.android.bluetooth(蓝牙进程
  3. 蓝牙进程启动之后,设置应用将直接与蓝牙进程通信,无需再经过系统服务进程。

2. Settings Process - 触发开启蓝牙

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,故会执行绑定服务的操作。

    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 这个服务,由以下配置信息可知,绑定的是 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>

蓝牙进程的启动过程由 蓝牙进程初始化 来分析,此文继续分析服务被绑定成功后的回调。

3.2 绑定 AdapterService 成功后的回调

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();

以上源码主要是创建了 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. 获取蓝牙进程蓝牙适配器服务的代理对象
                        mBluetooth = IBluetooth.Stub.asInterface(Binder.allowBlocking(service));
......
                        // 1. 向蓝牙进程注册回调函数,以达到双向通信的目的
                        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. 向蓝牙进程注册回调,用于蓝牙进程向系统服务进程发送消息;
  2. 执行应用层注册到系统服务进程的回调,向已注册的应用进程提供 蓝牙进程入口的代理对象;
  3. 向蓝牙进程发起执行 enable 操作的请求。

3.2.1 registerCallback

3.2.1.1 Register Flow

packages/apps/Bluetooth/src/com/android/bluetooth/btservice/AdapterService.java
AdapterService 存储该回调对象,在合适的时候触发回调。

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);
        }
    };

从以上源码可知,蓝牙进程调用该回调以通知系统服务进程蓝牙的状态变化信息。

    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() 负责更新状态,并发送状态变化的广播。

3.2.1.3 Callback Invoke Example

回调方法执行的源码如下
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 回调应用层注册的回调对象的方法 onBluetoothServiceUp(),将蓝牙进程入口的代理对象发送到该应用。

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

蓝牙进程继续执行 enable 操作的内容较多,链接如下。
Bluetooth initialization - enable in Bluetooth process

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,602评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,442评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,878评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,306评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,330评论 5 373
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,071评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,382评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,006评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,512评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,965评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,094评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,732评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,283评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,286评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,512评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,536评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,828评论 2 345

推荐阅读更多精彩内容