Android 9.0 Bluetooth源码分析(一)蓝牙开启流程

Android蓝牙打开和关闭的流程基本一致,这里就从打开的流程进行分析。

1 UI

从UI上看蓝牙开关就是设置settings里那个switch开关,蓝牙开关操作封装在Settings/bluetooth/BluetoothEnabler.java中,BluetoothEnabler便于蓝牙开关管理。里面实现SwitchBar.OnSwitchChangeListener接口,监听状态改变。

@Override
    public void onSwitchChanged(Switch switchView, boolean isChecked) {
          ...........
        //在LocalBluetoothAdapter中打开蓝牙
        if (mLocalAdapter != null) {
            mLocalAdapter.setBluetoothEnabled(isChecked);
        }
        mSwitch.setEnabled(false);
    }

onSwitchChanged里面调用LocalBluetoothAdapter的setBluetoothEnabled方法,这是蓝牙打开或者关闭的一个接口。接下来看一下LocalBluetoothAdapter:

    public void setBluetoothEnabled(boolean enabled) {
        boolean success = enabled ? mAdapter.enable() : mAdapter.disable();
           ......设置蓝牙状态.....
        }

LocalBluetoothAdapter在Settings app和Framworks之间提供了一个接口去改变蓝牙开关状态。setBluetoothEnabled调用BluetoothAdapter.enable方法。然后我们就进入framework的BluetoothAdapter中继续分析。


2 framework

public boolean enable() {
        int state = STATE_OFF;
        //已经打开返回
        if (isEnabled() == true){
            if (DBG) Log.d(TAG, "enable(): BT is already enabled..!");
            return true;
        }
        //Use service interface to get the exact state
        if (mService != null) {
            try {
               state = mService.getState();
            } catch (RemoteException e) {Log.e(TAG, "", e);}
        }
        //当前状态为打开
        if (state == BluetoothAdapter.STATE_BLE_ON) {
                Log.e(TAG, "BT is in BLE_ON State");
                notifyUserAction(true);
                return true;
        }
        try {
            //通过远程服务打开蓝牙
            return mManagerService.enable();
        } catch (RemoteException e) {Log.e(TAG, "", e);}
        return false;
    }

这个方法中的关键代码是“return mManagerService.enable();” mManagerService 对象是由IBluetoothManager 接口代码实现的,IBluetoothManager实际定义的是AIDL文件,对应的类就是 BluetoothManagerService 类,在路径 frameworks/base/core/java/android/bluetooth/BluetoothManagerService 下面 。

public boolean enable() {
       if (isBluetoothDisallowed()) {
           if (DBG) {
               Slog.d(TAG, "enable(): not enabling - bluetooth disallowed");
           }
           return false;
        }
        if ((Binder.getCallingUid() != Process.SYSTEM_UID) && (!checkIfCallerIsForegroundUser())) {
            Log.w(TAG,"enable(): not allowed for non-active and non system user");
            return false;
        }
        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
                         "Need BLUETOOTH ADMIN permission");//权限检查
        if (DBG) {
            Log.d(TAG,"enable():  mBluetooth =" + mBluetooth +
                    " mBinding = " + mBinding);
        }
        synchronized(mReceiver) {
            mQuietEnableExternal = false;
            mEnableExternal = true;
            // waive WRITE_SECURE_SETTINGS permission check 
            sendEnableMsg(false); //通过handler集中处理消息
        }
        if (DBG) Log.d(TAG, "enable returning");
        return true;
}

方法中先判断是否是系统app操作蓝牙,检查是否有操作蓝牙的权限等,然后关键的代码是“sendEnableMsg(false)”,handler最后调用handleEnable方法处理该消息。

private void handleEnable(boolean quietMode) {
    mQuietEnable = quietMode;
    synchronized(mConnection) {
    //检查服务是否已经启动并且已经绑定
    if ((mBluetooth == null) && (!mBinding)) {
        //Start bind timeout and bind
        Message timeoutMsg=mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND);
        mHandler.sendMessageDelayed(timeoutMsg,TIMEOUT_BIND_MS);
        mConnection.setGetNameAddressOnly(false);
        Intent i = new Intent(IBluetooth.class.getName());
        //绑定服务,UserHandle为多用户考虑
        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) {
        if (mConnection.isGetNameAddressOnly()) {
            // if GetNameAddressOnly is set, we can clear this flag,
            // so the service won't be unbind
            // after name and address are saved
            mConnection.setGetNameAddressOnly(false);
            //Register callback object
            try {
                mBluetooth.registerCallback(mBluetoothCallback);
            } catch (RemoteException re) {
                Log.e(TAG, "Unable to register BluetoothCallback",re);
            }
        //Inform BluetoothAdapter instances that service is up
        sendBluetoothServiceUpCallback();
    }
    //Enable bluetooth
    try {
        if (!mQuietEnable) {
            //使能蓝牙
            if (!mBluetooth.enable()) {
            Log.e(TAG,"IBluetooth.enable() returned false");
            }
        } else {
        if(!mBluetooth.enableNoAutoConnect()) {
                Log.e(TAG,"IBluetooth.enableNoAutoConnect() returned false");
             }
         }
    } catch (RemoteException e) {
        Log.e(TAG,"Unable to call enable()",e); 
    }
}

这里通过AIDL的方式,调用Bluetooth App 中的AdapterService 。先绑定服务,然后注册Ibluetooth回调函数,之后调用enable方法方法开启蓝牙。所以之后就从Framworks 跳到 Bluetooth APP 中继续分析。

——————————————————————————————————

3 Bluetooth APP

代码路径“Packages/apps/Bluetooth/src/com/android/bluetooth/btservice/AdapterService ”,看里面的 enable(boolean) 的实现

public synchronized boolean enable(boolean quietMode) {
         enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission");
         debugLog("enable() - Enable called with quiet mode status =  " + mQuietmode);
         mQuietmode = quietMode;
         //由状态机处理开启操作
         mAdapterStateMachine.sendMessage(AdapterState.BLE_TURN_ON);         
         return true;
     }

AdapterService.enable方法最终向状态机AdapterState发送AdapterState.BLE_TURN_ON消息,由状态机处理消息。蓝牙状态机的代码在Packages/apps/Bluetooth/src/com/android/bluetooth/btservice/AdapterState 下面,AdapterState状态机在AdapterService的onCreate方法中他通过一个静态函数AdapterState.make初始化。

private AdapterState(AdapterService service, AdapterProperties adapterProperties) {
        super("BluetoothAdapterState:");
        addState(mOnState);
        addState(mBleOnState);
        addState(mOffState);
        addState(mPendingCommandState);
        mAdapterService = service;
        mAdapterProperties = adapterProperties; 
        setInitialState(mOffState); //初始状态为offstate
    }

setInitialState设置了该状态机的初始状态是OffState,AdapterState.BLE_TURN_ON消息由OffState首先处理,状态机中每个状态通过调用public boolean processMessage方法处理每个消息。

        public boolean processMessage(Message msg) {
            AdapterService adapterService = mAdapterService;
            if (adapterService == null) {
          errorLog("Received message in OffState after cleanup: "+msg.what);
                return false;
            }
            debugLog("Current state: OFF, message: " + msg.what);
            switch(msg.what) {
                //初始状态是OffState,由OffState处理蓝牙开启操作
               case BLE_TURN_ON:
                   //通知BluetoothmangerService蓝牙正在开启
                   notifyAdapterStateChange(BluetoothAdapter.STATE_BLE_TURNING_ON);
                   mPendingCommandState.setBleTurningOn(true);
                   transitionTo(mPendingCommandState);
                   //发送延迟消息,检测打开超时任务
             sendMessageDelayed(BLE_START_TIMEOUT, BLE_START_TIMEOUT_DELAY);
                   //批量启动 profile service
                   adapterService.BleOnProcessStart();
                   break; 
               case USER_TURN_OFF:
                   //TODO: Handle case of service started
        //and stopped without enable
                   break; 
               default:
                   return false;
            }
            return true;
     }

BLE_TURN_ON里面通过回调通知BluetoothMangerService,蓝牙正在启动中,然后将状态机中下个状态设置为PendingCommandState,最后调用adapterService .BleOnProcessStart批量启动所需的各个profile server。

    void BleOnProcessStart() {
        debugLog("BleOnProcessStart()");
        //支持的profile service
        Class[] supportedProfileServices = Config.getSupportedProfiles();
        //Initialize data objects
        for (int i=0; i < supportedProfileServices.length;i++) {
            mProfileServicesState.put(supportedProfileServices[i].getName(),
                    BluetoothAdapter.STATE_OFF);
        }
     //初始化远程蓝牙设备
        mRemoteDevices = new RemoteDevices(this);
        mAdapterProperties.init(mRemoteDevices);
        debugLog("BleOnProcessStart() - Make Bond State Machine");
        //启动蓝牙绑定状态状态
        mBondStateMachine = BondStateMachine.make(this, mAdapterProperties, mRemoteDevices);
        mJniCallbacks.init(mBondStateMachine,mRemoteDevices);
        //FIXME: Set static instance here???
        setAdapterService(this);
        //Start Gatt service
        setGattProfileServiceState(supportedProfileServices,BluetoothAdapter.STATE_ON);
}

BleOnProcessStart首先获取支持的profile,支持的profile在 Config.java 中。接着启动新的状态机BondStateMachine,最后调用setGattProfileServiceState方法,批量启动支持的Profile server,包括GattService,启动服务时会传入参数:ACTION_SERVICE_STATE_CHANGED和BluetoothAdapter.STATE_ON 。

然后看packages/apps/Bluetooth/src/com/android/bluetooth/gatt/GattService.java启动的入口onStartCommand,里面没有什么内容,真正的实现在父类中:

    public int onStartCommand(Intent intent, int flags, int startId) {
        if (DBG) log("onStartCommand()");
        if (mStartError || mAdapter == null) {
          Log.w(mName, "Stopping profile service: device does not have BT");
            doStop(intent);
            return PROFILE_SERVICE_MODE;
        }
        if (checkCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM) != PackageManager.PERMISSION_GRANTED) {
            Log.e(mName, "Permission denied!");
            return PROFILE_SERVICE_MODE;
        }
        if (intent == null) {
            Log.d(mName, "Restarting profile service...");
            return PROFILE_SERVICE_MODE;
        } else {
        String action = intent.getStringExtra(AdapterService.EXTRA_ACTION);
           if (AdapterService.ACTION_SERVICE_STATE_CHANGED.equals(action)) {
                int state= intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);
                if(state==BluetoothAdapter.STATE_OFF) {
                 Log.d(mName, "Received stop request...Stopping profile...");
                    doStop(intent); //停止
                } else if (state == BluetoothAdapter.STATE_ON) {
                 Log.d(mName, "Received start request. Starting profile...");
                    doStart(intent); //启动
                }}}
        return PROFILE_SERVICE_MODE;
    }

因为启动服务时传入的参数是ACTION_SERVICE_STATE_CHANGED和BluetoothAdapter.STATE_ON,所以调用doStart。doStart里面调用了抽象方法start(实现是在子类GattService里面,做了一些预处理,包括initializeNative、启动一些manager)再调notifyProfileServiceStateChanged(BluetoothAdapter.STATE_ON),此方法会调用AdapterService.onProfileServiceStateChanged方法,传递STATE_ON消息,该消息会包装在MESSAGE_PROFILE_SERVICE_STATE_CHANGED类型里,由AdapterService的handler方法处理

    private final Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            debugLog("handleMessage() - Message: " + msg.what);
            switch (msg.what) {
                case MESSAGE_PROFILE_SERVICE_STATE_CHANGED: 
                    debugLog("handleMessage() - MESSAGE_PROFILE_SERVICE_STATE_CHANGED");
                    processProfileServiceStateChanged((String) msg.obj, msg.arg1);
                    break;
            }
                 ........................
            }
        }
    };

processProfileServiceStateChanged处理profile 状态改变,里面

//在OffState中,isBleTurningOn设置为true
    if (isBleTurningOn) {
         if (serviceName.equals("com.android.bluetooth.gatt.GattService")) {
                debugLog("GattService is started");
                mAdapterStateMachine.sendMessage(mAdapterStateMachine.
                        obtainMessage(AdapterState.BLE_STARTED));
                return;
            }
    }

会向AdapterStateMachine状态机发送BLE_STARTED消息,根据之前状态机已经由OffState切换成PendingCommandState,所以消息由PendingCommandState状态处理,看processMessage的处理

                case BLE_STARTED:
                    //Remove start timeout
                    removeMessages(BLE_START_TIMEOUT);
                    //Enable,调用底层方法,开启蓝牙
                    if (!adapterService.enableNative()) {
                        errorLog("Error while turning Bluetooth on");
                        //开启失败,状态通知,切换到OffState状态
                        notifyAdapterStateChange(BluetoothAdapter.STATE_OFF);
                        transitionTo(mOffState);
                    } else {
                    //超时检测
                    sendMessageDelayed(ENABLE_TIMEOUT, ENABLE_TIMEOUT_DELAY);
                    }
                break;

通过调用adapterService.enableNative()方法,开始调用JNI方法,进入C/C++层。adapterService.enableNative对应的cpp文件为Packages/apps/Bluetooth/jni/com_android_bluetooth_btservice_AdapterService.cpp:

static jboolean enableNative(JNIEnv* env, jobject obj) {
    ALOGV("%s:",__FUNCTION__);
jboolean result = JNI_FALSE;
 if (!sBluetoothInterface) return result;
 int ret = sBluetoothInterface->enable();
    result = (ret == BT_STATUS_SUCCESS || ret == BT_STATUS_DONE) ? JNI_TRUE : JNI_FALSE; //判断是打开还是关闭状态;
    return result;
}

通过调用“int ret = sBluetoothInterface->enable()”来驱动底层打开蓝牙开关。接下来就是C里面对打开蓝牙的实现。

——————————————————————————————————

4 蓝牙协议栈

对应的代码在/system/bt/btif/src/bluetooth.cc里面:

static int enable(void) {
  LOG_INFO("%s", __func__);
  if (!interface_ready())//状态判断,已经初始化,向下执行
    return BT_STATUS_NOT_READY;
  stack_manager_get_interface()->start_up_stack_async();
  return BT_STATUS_SUCCESS;
}

enable方法会调用start_up_stack_async方法,start_up_stack_async的实现在stack_manager.c 文件中:

static void start_up_stack_async(void) {
    thread_post(management_thread, event_start_up_stack, NULL);
}

通过thread_post异步event_start_up_stack,来启动蓝牙栈

// Synchronous function to start up the stack
static void event_start_up_stack(UNUSED_ATTR void *context) {
  if (stack_is_running) {
LOG_DEBUG("%s stack already brought up.", __func__);
    return;
  }
  ensure_stack_is_initialized();//确保,栈已经初始化
  LOG_DEBUG("%s is bringing up the stack.", __func__);
  hack_future = future_new();
  // Include this for now to put btif config into a shutdown-able state
  //加载配置文件,配置文件位于手机系统目录/data/misc/bluedroid/bt_config.xml
  module_start_up(get_module(BTIF_CONFIG_MODULE));
  bte_main_enable();//BTE部分的enable
  if (future_await(hack_future) != FUTURE_SUCCESS) {//启动失败
    stack_is_running = true; // So stack shutdown actually happens    
    event_shut_down_stack(NULL); //关闭蓝牙栈,里面还会调用
    return;}
  stack_is_running = true;
  LOG_DEBUG("%s finished", __func__);
btif_thread_post(event_signal_stack_up, NULL); //发送蓝牙栈启动信息:
}

bte_main_enable()方法中进行btsnoop_module和hci_module的启动以及启动BTU操作,这里就不深入下去了。

如果打开蓝牙成功,走到btif_thread_post(event_signal_stack_up, NULL)这里,会在event_signal_stack_up函数里面调用HAL_CBACK(bt_hal_cbacks, adapter_state_changed_cb, BT_STATE_ON) ,然后通过回调调用adapter_state_changed_cb方法,通知蓝牙当前状态BT_STATE_ON。

adapter_state_changed_cb在hardware/libhardware/include/hardware/bluetooth.h文件中被定义:

/** Bluetooth DM callback structure. */
typedef struct {
    /** set to sizeof(bt_callbacks_t) */
    size_t size;
    adapter_state_changed_callback adapter_state_changed_cb;
    ...........
} bt_callbacks_t;

如果C++层有消息传递到java层,回调接口都定义在这里,adapter_state_changed_cb对应的是adapter_state_changed_callback 。然后通过JNI回调通知到JAVA层,上层就会收到打开蓝牙的通知。至此,打开蓝牙流程分析到这里。


参考文档

  1. https://www.2cto.com/kf/201411/352236.html
  2. https://blog.csdn.net/xubin341719/article/details/40402637
  3. https://www.jianshu.com/p/181ad20a5bff
  4. https://blog.csdn.net/shichaog/article/details/52728684
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念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