美文网首页android源码Android开发Android开发
Android 9.0 Bluetooth源码分析(一)蓝牙开启

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

作者: 猫疏 | 来源:发表于2019-03-21 19:12 被阅读5次

    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

    相关文章

      网友评论

        本文标题:Android 9.0 Bluetooth源码分析(一)蓝牙开启

        本文链接:https://www.haomeiwen.com/subject/wiacvqtx.html