Android 蓝牙启动流程(以及设置蓝牙为作为sink模式 & 接收端模式)

Stella981
• 阅读 1091

本文以Android 7.1为基础

最近在做蓝牙开发,研究了一下蓝牙的启动流程,总结一下

Google在Android源码中推出了它和博通公司一起开发的BlueDroid以替代BlueZ。BlueZ的创始者,高通公司也将在基于其芯片的Android参考设计中去除BlueZ,支持BlueDroid。相比BlueZ,BlueDroid最值得称道的地方就是其框架结构变得更为简洁和清晰。对我们工程师来说这也是个不错的福利,清晰、简洁的架构使我们在debug过程中思路更清晰;

蓝牙的总体流程图

从流程图我们可以看出来 蓝牙应用通过binder和系统蓝牙Service进行通讯 ,然后通过Jin与蓝牙HAL层进行通讯.

Android 蓝牙启动流程(以及设置蓝牙为作为sink模式 & 接收端模式)

按层级划分

Android 蓝牙启动流程(以及设置蓝牙为作为sink模式 & 接收端模式)

Bluetooth Service(Java层)代码路径

frameworks/base/core/java/Android/Bluetooth:

Bluetooth 应用层代码路径

packages/apps/Bluetooth

Bluetooth协议层代码

system/bt/

涉及的总共路径:

frameworks/base/core/java/android/bluetooth/BluetoothAdapter.java
frameworks/base/core/java/android/bluetooth/BluetoothManagerService.java
packages/apps/Bluetooth/src/com/android/bluetooth/btservice/AdapterService.java
packages/apps/Bluetooth/src/com/android/bluetooth/btservice/AdapterState.java
packages/apps/Bluetooth/jni/com_android_bluetooth_btservice_AdapterService.cpp
system/bt/btif/src/btif_dm.c
system/bt/btif/include/btif_common.h
hardware/libhardware/include/hardware/bluetooth.h 

一.将蓝牙作为sink模式 配置

sink模式一般是车机端需要设置的模式,用于链接手机之后可以播放蓝牙音乐,获取联系人,和电话控制等等

packages/apps/Bluetooth/src/com/android/bluetooth/btservice/Config.java
有如下两个参数控制是否是 sink端

boolean isA2dpSinkEnabled = SystemProperties.getBoolean("persist.service.bt.a2dp.sink", false);
        boolean isHfpClientEnabled = SystemProperties.getBoolean("persist.service.bt.hfp.client",false);

我们需要在编译源码的时候去配置成sink模式

device/qcom/msmxxx_64/system.prop
添加如下配置

persist.service.bt.a2dp.sink=true
persist.service.bt.hfp.client=true

再具体的配置信息在如下配置中进行设置具体支持那种profile

packages/apps/Bluetooth/res/values/config.xml

<resources>
    <bool name="profile_supported_a2dp">true</bool>
    <bool name="profile_supported_a2dp_sink">false</bool>
    <bool name="profile_supported_hdp">true</bool>
    <bool name="profile_supported_hs_hfp">true</bool>
    <bool name="profile_supported_hfpclient">false</bool>
    <bool name="profile_supported_hid">true</bool>
    <bool name="profile_supported_opp">true</bool>
    <bool name="profile_supported_pan">true</bool>
    <bool name="profile_supported_pbap">true</bool>
    <bool name="profile_supported_gatt">true</bool>
    <bool name="pbap_include_photos_in_vcard">true</bool>
    <bool name="pbap_use_profile_for_owner_vcard">true</bool>
    <bool name="profile_supported_map">true</bool>
    <bool name="profile_supported_avrcp_controller">false</bool>
    <bool name="profile_supported_sap">false</bool>
    <bool name="profile_supported_pbapclient">false</bool>
    <bool name="strict_location_check">true</bool>
</resources>

当然修改上面的配置我们可以在如下路径配置

vendor/qcom/opensource/bluetooth/res/values/config.xml


<resources>
    <bool name="profile_supported_ftp">true</bool>
    <bool name="profile_supported_map">false</bool>
    <bool name="profile_supported_sap">true</bool>
    <bool name="profile_supported_dun">true</bool>
</resources>

如果 packages/apps/Bluetooth/res/values/config.xml 和 vendor/qcom/opensource/bluetooth/res/values/config.xml 都配置了如下配置 或者是配置的两个Boolean 值是反向的,系统会依据 vendor/qcom/opensource/bluetooth/res/values/config.xml 配置为最终结果,配置完成之后编译系统,烧录系统就可以作为sink端使用,也就是接收端.

二.启动流程分析

首先我们调用蓝牙的时候使用的是Bluetooth的 BluetoothAdapter.java 类 中的enable方法

路径如下

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

    public boolean enable() {
        android.util.SeempLog.record(56);
        if (isEnabled()) {
            if (DBG) Log.d(TAG, "enable(): BT already enabled!");
            return true;
        }
        try {
            // 此处调用的是  IBluetoothManager.java的 enable
            return mManagerService.enable(ActivityThread.currentPackageName());
        } catch (RemoteException e) {Log.e(TAG, "", e);}
        return false;
    }

我们查看到 IBluetoothManager.java的实现类是BluetoothManagerService.java , BluetoothManagerService.java

class BluetoothManagerService extends IBluetoothManager.Stub {
 .....省略代码.....
  public boolean enable(String packageName) throws RemoteException {
        final int callingUid = Binder.getCallingUid();
        final boolean callerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID;
        .....省略代码.....
        // 权限检查
        .....省略代码.....

        synchronized(mReceiver) {
            mQuietEnableExternal = false;
            mEnableExternal = true;
            // waive WRITE_SECURE_SETTINGS permission check
            sendEnableMsg(false, packageName);
        }
        if (DBG) Slog.d(TAG, "enable returning");
        return true;
    }
 .....省略代码.....
}

我们继续查看可以看到调用的是 sendEnableMsg(boolean quietMode, String packageName) 方法.

    private void sendEnableMsg(boolean quietMode, String packageName) {
        mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_ENABLE,
                             quietMode ? 1 : 0, 0));
        addActiveLog(packageName, true);
    }

在sendEnableMsg 方法中 发送了一个message消息 MESSAGE_ENABLE

    case MESSAGE_ENABLE:
                    
                    try {
                        if (mBluetooth != null) {
                            int state = mBluetooth.getState();
                            if (state == BluetoothAdapter.STATE_BLE_ON) {
                                //如果蓝牙已经打开调用 BluetoothAdapterService.java 开启profile
                                mBluetooth.onLeServiceUp();
                                //保存蓝牙的开关状态
                                persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH);
                                break;
                            }
                        }
                    }
                    mQuietEnable = (msg.arg1 == 1);
                    //如果没有蓝牙没有打开去打开蓝牙
                    if (mBluetooth == null) {
                        handleEnable(mQuietEnable);
                    } else {
                     
                        if(state == BluetoothAdapter.STATE_TURNING_OFF || state == BluetoothAdapter.STATE_BLE_TURNING_OFF)
                            waitForMonitoredOnOff(false, true);
                        //重启蓝牙
                        Message restartMsg = mHandler.obtainMessage(
                                MESSAGE_RESTART_BLUETOOTH_SERVICE);
                        mHandler.sendMessageDelayed(restartMsg,
                                2 * SERVICE_RESTART_TIME_MS);
                    }
                    break;

在 MESSAGE_ENABLE 接收的消息中会先判断盘牙是否打开,如果已经打开 就调用mBluetooth.onLeServiceUp();去打开 Profile文件如果没有打开就调用handleEnable(mQuietEnable);去打开蓝牙. 咱们这里先不看 mBluetooth.onLeServiceUp(); 方法先查看handleEnable(mQuietEnable)

private void handleEnable(boolean quietMode) {
      
            if ((mBluetooth == null) && (!mBinding)) {
                //蓝牙打开超时记录
                Message timeoutMsg=mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND);
                mHandler.sendMessageDelayed(timeoutMsg,TIMEOUT_BIND_MS);
                Intent i = new Intent(IBluetooth.class.getName());
                //此处我们查看到  mConnection 方法是链接状态的回调 
                if (!doBind(i, mConnection,Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT,
                        UserHandle.CURRENT)) {
                    mHandler.removeMessages(MESSAGE_TIMEOUT_BIND);
                } else {
                    mBinding = true;
                }
            } 
    }

其中mConnection 是链接的回调 BluetoothServiceConnection 就是 mConnection 类

在BluetoothServiceConnection 类中会发送   MESSAGE_BLUETOOTH_SERVICE_CONNECTED 消息并传递了一个 AdapterService对象.

 private class BluetoothServiceConnection implements ServiceConnection {
        public void onServiceConnected(ComponentName componentName, IBinder service) {
            String name = componentName.getClassName();
            if (DBG) Slog.d(TAG, "BluetoothServiceConnection: " + name);
            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);
        }

        public void onServiceDisconnected(ComponentName componentName) {
            // Called if we unexpectedly disconnect.
            String name = componentName.getClassName();
            if (DBG) Slog.d(TAG, "BluetoothServiceConnection, disconnected: " + name);
            Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED);
            if (name.equals("com.android.bluetooth.btservice.AdapterService")) {
                msg.arg1 = SERVICE_IBLUETOOTH;
            }
            mHandler.sendMessage(msg);
        }
    }

我们继续追踪  MESSAGE_BLUETOOTH_SERVICE_CONNECTED消息

     case MESSAGE_BLUETOOTH_SERVICE_CONNECTED:
                {
                    IBinder service = (IBinder) msg.obj;
                    mBinding = false;
                    mBluetoothBinder = service;
                    mBluetooth = IBluetooth.Stub.asInterface(service);
                    //注册 CallBack 重要,后面的回调要使用
                    try {
                        mBluetooth.registerCallback(mBluetoothCallback);
                    } catch (RemoteException re) {
                        Slog.e(TAG, "Unable to register BluetoothCallback",re);
                    }
                    //Do enable request
                    try {
                        //打开蓝牙请求
                        if (mQuietEnable == false) {
                            if (!mBluetooth.enable()) {
                                Slog.e(TAG,"IBluetooth.enable() returned false");
                            }
                        }
                    }
                    break;
                }

MESSAGE_BLUETOOTH_SERVICE_CONNECTED消息里面可以查看到 mBluetooth = IBluetooth.Stub.asInterface(service);获取的是 IBluetooth 对象 , 而AdapterService.java 内部类 AdapterServiceBinder  实现了 IBluetooth

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

  private static class AdapterServiceBinder extends IBluetooth.Stub {
        private AdapterService mService;

        public AdapterService getService() {
            if (mService != null && mService.isAvailable()) {
                return mService;
            }
            return null;
        }

      public boolean enable() {
           ........
            AdapterService service = getService();
            if (service == null) return false;
            return service.enable();
        }
    }

由上面可以看出 return service.enable();调用的是 AdapterService.java 中的方法 enable() 方法

   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;
         Message m = mAdapterStateMachine.obtainMessage(AdapterState.BLE_TURN_ON);
         mAdapterStateMachine.sendMessage(m);
         mBluetoothStartTime = System.currentTimeMillis();
         return true;
     }

发送的是 BLE_TURN_ON

packages/apps/Bluetooth/src/com/android/bluetooth/btservice/AdapterState.java 接受了这个消息

          case BLE_TURN_ON:
                   notifyAdapterStateChange(BluetoothAdapter.STATE_BLE_TURNING_ON);
                   //将蓝牙的状态转换成 mPendingCommandState
                   mPendingCommandState.setBleTurningOn(true);
                   transitionTo(mPendingCommandState);
                   sendMessageDelayed(BLE_START_TIMEOUT, BLE_START_TIMEOUT_DELAY);
                   adapterService.BleOnProcessStart();
                   break;

将了蓝牙的状态转换成 mPendingCommandState 调用 BleOnProcessStart 方法,也可以在supportedProfileServices  方法中去掉自己不想开启的ProfileService.

   void BleOnProcessStart() { 
        
        //获取支持的profile 文件
        Class[] supportedProfileServices = Config.getSupportedProfiles();
        //Initialize data objects
        for (int i=0; i < supportedProfileServices.length;i++) {
            mProfileServicesState.put(supportedProfileServices[i].getName(),BluetoothAdapter.STATE_OFF);
        }
        mRemoteDevices.cleanup();
        mAdapterProperties.init(mRemoteDevices);
        mJniCallbacks.init(mBondStateMachine,mRemoteDevices);
        //Start Gatt service
        //调用 ProfileService
        setGattProfileServiceState(supportedProfileServices,BluetoothAdapter.STATE_ON);
    }

获取支持的ProfileService列表.

  private static final Class[] PROFILE_SERVICES = {
        HeadsetService.class,
        A2dpService.class,
        A2dpSinkService.class,
        HidService.class,
        HealthService.class,
        PanService.class,
        GattService.class,
        BluetoothMapService.class,
        HeadsetClientService.class,
        AvrcpControllerService.class,
        SapService.class,
        PbapClientService.class
    };

//发送  ACTION_SERVICE_STATE_CHANGED参数 每一个profile 都有 遍历开启 profile

  private void setGattProfileServiceState(Class[] services, int state) {

        for (int i=0; i <services.length;i++) {
                mProfileServicesState.put(serviceName,pendingState);
                Intent intent = new Intent(this,services[i]);
                intent.putExtra(EXTRA_ACTION,ACTION_SERVICE_STATE_CHANGED);
                intent.putExtra(BluetoothAdapter.EXTRA_STATE,state);
                startService(intent);
                return;
            }
        }
    }

  public int onStartCommand(Intent intent, int flags, int startId) {
        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)) {
                } else if (state == BluetoothAdapter.STATE_ON) {
                       ........省略代码......
                        // 开启服务
                         doStart(intent);
                }
        }
        return PROFILE_SERVICE_MODE;
    }

 调用doStartService之后 我们可以看到调用了 notifyProfileServiceStateChanged 方法。

  private void doStart(Intent intent) {
   
            if (!mStartError) {
               // 开始调用 notifyProfileServiceStateChanged
                notifyProfileServiceStateChanged(BluetoothAdapter.STATE_ON);
            } 
    }

继续查看notifyProfileServiceStateChanged 方法 ,里面又回到了AdapterServer 中的 onProfileServiceStateChanged方法

  protected void notifyProfileServiceStateChanged(int state) {
        //Notify adapter service
        AdapterService adapterService = AdapterService.getAdapterService();
        if (adapterService != null) {
            adapterService.onProfileServiceStateChanged(getClass().getName(), state);
        }
    }

发送MESSAGE_PROFILE_SERVICE_STATE_CHANGED 消息 给消息处理

   public void onProfileServiceStateChanged(String serviceName, int state) {
        Message m = mHandler.obtainMessage(MESSAGE_PROFILE_SERVICE_STATE_CHANGED);
        m.obj=serviceName;
        m.arg1 = state;
        mHandler.sendMessage(m);
    }

在消息接收的地方查看到蓝牙的 processProfileServiceStateChanged 方法被调用,在processProfileServiceStateChanged 方法中发送了 BLE_STARTED 消息,而这个消息接受的地方是开起底层ProfileService的地方。

       case MESSAGE_PROFILE_SERVICE_STATE_CHANGED: {
                    debugLog("handleMessage() - MESSAGE_PROFILE_SERVICE_STATE_CHANGED");
                    processProfileServiceStateChanged((String) msg.obj, msg.arg1);
                }
                    break;

   private void processProfileServiceStateChanged(String serviceName, int state) {
    
        if (isBleTurningOn) {
            if (serviceName.equals("com.android.bluetooth.gatt.GattService")) {
                debugLog("GattService is started");
                mAdapterStateMachine.sendMessage(mAdapterStateMachine.obtainMessage(AdapterState.BLE_STARTED));
                return;
            }

        } 
    }

/packages/apps/Bluetooth/src/com/android/bluetooth/btservice/AdapterState.java BLE_STARTED消息处理任务,通过 adapterService.enableNative(isGuest) 开启底层的profileService。

         case BLE_STARTED:
                   //开启底层服务
                    if (!adapterService.enableNative(isGuest)) {
                        errorLog("Error while turning Bluetooth on");
                        notifyAdapterStateChange(BluetoothAdapter.STATE_OFF);
                        transitionTo(mOffState);
                    }
                    break;

调用的是 AdapterService.java 中的native方法 ,根据包名和JNI 方法的名称我们可以推算出来调用的CPP的名称是 com_android_bluetooth_btservice_AdapterService.cpp

 /*package*/ native boolean enableNative(boolean startRestricted);

在如下路径找到了 packages/apps/Bluetooth/jni/com_android_bluetooth_btservice_AdapterService.cpp 在enableNative中查看到 int ret = sBluetoothInterface->enable(isGuest == JNI_TRUE ? 1 : 0); 调用的是 sBluetoothInterface 中的enable方法

static jboolean enableNative(JNIEnv* env, jobject obj, jboolean isGuest) {
    ALOGV("%s:",__FUNCTION__);

    jboolean result = JNI_FALSE;
    if (!sBluetoothInterface) return result;
    int ret = sBluetoothInterface->enable(isGuest == JNI_TRUE ? 1 : 0);
    result = (ret == BT_STATUS_SUCCESS || ret == BT_STATUS_DONE) ? JNI_TRUE : JNI_FALSE;
    return result;
}

具体的实现在 bluetooth.c中。

/system/bt/btif/src/bluetooth.c

static int enable(bool start_restricted) {
  LOG_INFO(LOG_TAG, "%s: start restricted = %d", __func__, start_restricted);

  restricted_mode = start_restricted;

  if (!interface_ready())
    return BT_STATUS_NOT_READY;

  stack_manager_get_interface()->start_up_stack_async();
  return BT_STATUS_SUCCESS;
}

底层回调传递到上层的时候主要使用的是 btif_dm.c 中对消息的处理 BTA_DM_INQ_RES_EVT 消息

system/bt/btif/src/btif_dm.c

static void btif_dm_search_devices_evt (UINT16 event, char *p_param)
{ 
    ...省略代码.....
    case BTA_DM_INQ_RES_EVT:
     ...省略代码.....
 /* Callback to notify upper layer of device */
              HAL_CBACK(bt_hal_cbacks, device_found_cb,
                                num_properties, properties);
          
        break;

/system/bt/btif/include/btif_common.h

define HAL_CBACK(P_CB, P_CBACK, ...) 方法 , HAL_CBACK就是一宏定义,就是调用结构体中对应的方法

extern bt_callbacks_t *bt_hal_cbacks;

#define HAL_CBACK(P_CB, P_CBACK, ...)\
    if (P_CB && P_CB->P_CBACK) {            \
        BTIF_TRACE_API("HAL %s->%s", #P_CB, #P_CBACK); \
        P_CB->P_CBACK(__VA_ARGS__);         \
    }                                       \
    else {                                  \
        ASSERTC(0, "Callback is NULL", 0);  \
    }

bt_hal_cbacks 其实就是 蓝牙AdapterService中调用了initNative方法传入到底层的。看下jni中的initNative方法:

 @Override
    public void onCreate() {
        super.onCreate();
        ..........
        //调用底层方法
       initNative();

       ........

    }

private native boolean initNative();

调用com_android_bluetooth_btservice_AdapterService.cpp init方法 将Callback传递到底层

static bool initNative(JNIEnv* env, jobject obj) {
            .......
            //调用com_android_bluetooth_btservice_AdapterService.cpp init方法 将Callback传递到底层
            // 再调用 bluetooth.c 的 init方法

        int ret = sBluetoothInterface->init(&sBluetoothCallbacks);
              
            .......
}

com_android_bluetooth_btservice_AdapterService.cpp  再调用 bluetooth.c 的 init方法

static int init(bt_callbacks_t *callbacks) {
  CallBack传递到底层
  bt_hal_cbacks = callbacks;
  stack_manager_get_interface()->init_stack();

}

其实这里有两个地方有  bt_callbacks_t  我们可以对比看一下

1./hardware/libhardware/include/hardware/bluetooth.h

2. /packages/apps/Bluetooth/jni/com_android_bluetooth_btservice_AdapterService.cpp

bluetooth.h 中的 bt_callbacks_t

typedef struct {
    /** set to sizeof(bt_callbacks_t) */
    size_t size;
    adapter_state_changed_callback adapter_state_changed_cb;
    adapter_properties_callback adapter_properties_cb;
    remote_device_properties_callback remote_device_properties_cb;
    device_found_callback device_found_cb;
    discovery_state_changed_callback discovery_state_changed_cb;
    pin_request_callback pin_request_cb;
    ssp_request_callback ssp_request_cb;
    bond_state_changed_callback bond_state_changed_cb;
    acl_state_changed_callback acl_state_changed_cb;
    callback_thread_event thread_evt_cb;
    dut_mode_recv_callback dut_mode_recv_cb;
    le_test_mode_callback le_test_mode_cb;
    energy_info_callback energy_info_cb;
} bt_callbacks_t;



// com_android_bluetooth_btservice_AdapterService.cpp 中的 bt_callbacks_t
static bt_callbacks_t sBluetoothCallbacks = {
    sizeof(sBluetoothCallbacks),
    adapter_state_change_callback,
    adapter_properties_callback,
    remote_device_properties_callback,
    device_found_callback,
    discovery_state_changed_callback,
    pin_request_callback,
    ssp_request_callback,
   bond_state_changed_callback,
    acl_state_changed_callback,
    callback_thread_event,
    dut_mode_recv_callback,
    le_test_mode_recv_callback,
    energy_info_recv_callback
};

static bt_callbacks_t sBluetoothCallbacks = {
    sizeof(sBluetoothCallbacks),
    adapter_state_change_callback,
    adapter_properties_callback,
    remote_device_properties_callback,
    device_found_callback,
    discovery_state_changed_callback,
    pin_request_callback,
    ssp_request_callback,
   bond_state_changed_callback,
    acl_state_changed_callback,
    callback_thread_event,
    dut_mode_recv_callback,
    le_test_mode_recv_callback,
    energy_info_recv_callback
};

最后蓝牙驱动打开之后会通过

/system/bt/btif/src/btif_core.c 中的 btif_enable_bluetooth_evt(tBTA_STATUS status) 回调给应用

void btif_enable_bluetooth_evt(tBTA_STATUS status){
  // 省略代码
 HAL_CBACK(bt_hal_cbacks, adapter_properties_cb, BT_STATUS_SUCCESS, 1, &prop);
}

然后回调给 adapter_properties_callback:返回手机蓝牙设备的地址、名称、UUID

adapter_state_change_callback 回调 通过 C调用 Java的代码 callbackEnv->CallVoidMethod(sJniCallbacksObj, method_stateChangeCallback, (jint)status);  返回给应用中的也就是回调java层代码 JniCallback.java文件中stateChangeCallback方法。这时跳转到AdapterState.java中,执行stateChangeCallback()方法;发送了ENABLED_READY消息。根据以上分析,这时状态机还处于PendingCommandState,在该状态下处理ENABLED_READY消息,

 case ENABLED_READY:
                   removeMessages(ENABLE_TIMEOUT);
                   mPendingCommandState.setBleTurningOn(false);
                   transitionTo(mBleOnState);
                   notifyAdapterStateChange(BluetoothAdapter.STATE_BLE_ON);
                   break;

做下面两个动作:状态切换到mOnState;更新adapterProperties中的蓝牙状态信息;通知蓝牙状态变为打开。具体看下notifyAdapterStateChange方法。主要是调用了adapterService类的方法。

private void notifyAdapterStateChange(int newState) {
        AdapterService adapterService = mAdapterService;
        AdapterProperties adapterProperties = mAdapterProperties;
        if ((adapterService == null) || (adapterProperties == null)) {
            errorLog("notifyAdapterStateChange after cleanup:" + newState);
            return;
        }

        int oldState = adapterProperties.getState();
        adapterProperties.setState(newState);
        infoLog("Bluetooth adapter state changed: " + oldState + "-> " + newState);
        adapterService.updateAdapterState(oldState, newState);
    }

adapterService.updateAdapterState(oldState, newState); 
来到adapterService类。

  void updateAdapterState(int prevState, int newState){
        if (mCallbacks !=null) {
            int n=mCallbacks.beginBroadcast();
            debugLog("updateAdapterState() - Broadcasting state to " + n + " receivers.");
            for (int i=0; i <n;i++) {
                try {
// 完成回调 发送广播给调用者                    

mCallbacks.getBroadcastItem(i).onBluetoothStateChange(prevState,newState);
                }  catch (RemoteException e) {
                    debugLog("updateAdapterState() - Callback #" + i + " failed ("  + e + ")");
                }
            }
            mCallbacks.finishBroadcast();
        }
    }

之前在打开蓝牙操作初期,在BluetoothManagerService中注册了回调方法,因此又跳转到framework中,执行回调方法。蓝牙打开从framework公共接口开始调用enable方法,执行到bluetooth.apk中,在该应用中通过jni注册回调方法和调用hal层打开蓝牙方法,在驱动层完成蓝牙上电等操作后,通过hal-jni回调到应用层中,应用通过aidl回调通知framework蓝牙状态变化,framework发送广播通知大家蓝牙打开。

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
4个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Stella981 Stella981
3年前
Opencv中Mat矩阵相乘——点乘、dot、mul运算详解
Opencv中Mat矩阵相乘——点乘、dot、mul运算详解2016年09月02日00:00:36 \牧野(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fme.csdn.net%2Fdcrmg) 阅读数:59593
Stella981 Stella981
3年前
KVM调整cpu和内存
一.修改kvm虚拟机的配置1、virsheditcentos7找到“memory”和“vcpu”标签,将<namecentos7</name<uuid2220a6d1a36a4fbb8523e078b3dfe795</uuid
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
10个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这