【Android4.4蓝牙代码分析】- 蓝牙Enable过程

转载:http://blog.csdn.net/wenbo13579/article/details/47083923

【Android4.4蓝牙代码分析】- 蓝牙Enable过程

(一)基本说明

  1. 本文的代码选用的是Android4.4kitkat代码。

  2. 本文是在Windows环境下通过source insight进行代码阅读,所以大部分目录是以windows的目录结构以’\’区分层级关系。


(二)搭建代码环境

首先介绍下本文source insight所加载的代码路径,bluedroid代码结构可以参考BlueDroid概述

  1. package/apps/Bluetooth,这个目录下是Bluetooth的app源码。
  2. hardware/libhardware/include/hardware,JNI层的一些代码。
  3. external/Bluetooth/bluedroid,bluedroid协议栈代码。
  4. frameworks\base\core\java\android\bluetooth,framework层的java代码与aidl文件。
  5. packages\apps\Settings\src\com\android\settings\bluetooth,Setting App源码中的bluetooth代码
  6. frameworks\base\services\java\com\android\server,系统核心服务的代码,系统启动后会在这注册蓝牙服务。

(三)蓝牙enable好文分享

有关于Android bluedroid的enable分析已经有很多大牛分析了,现在分享出部分好的博客,本文很多东西都是参考他们的文章。

  1. Android BlueDroid(三):BlueDroid蓝牙开启过程enable,该文给出了总体的流程图,在总体结构上对蓝牙enable过程可以有个清晰的认识。
  2. Android 4.2 Bluetooth 分析总结(二) 蓝牙enable 的整个过程,该文给出了log,并且按照代码运行流程一个个函数的进行分析,本文很多内容都参考至该文。
  3. android bluetooth 移植相关注意事项,该文将了下蓝牙移植的相关知识,在进行代码阅读之前看看该文,能够从一个总体层次上对bluedroid代码进行分析。
  4. android – 蓝牙 bluetooth (二) 打开蓝牙,该文是也很不错,作者最开始就是看的该博客。

(四)代码分析

在Android系统启动过程中,其会首先加载SystemServer.java,System Server是Android系统的核心,他在Dalvik虚拟机启动后立即开始初始化和运行。其它的系统服务在System Server进程的环境中运行。在Android系统开机过程中,蓝牙服务也会在这里注册,并运行,关于SystemServer.java详见(Android的System Server),这样蓝牙服务进程就作为一个线程运行在SystemServer进程中。最后一个else分支是我们所关心的,通过ServiceManager.addService方法向ServiceManager进程中注册了蓝牙服务,后面要使用时只需要通过getService(BluetoothAdapter.BLUETOOTH_MANAGER_SERVICE)方法即可(BluetoothAdapter类在frameworks\base\core\java\android\bluetooth目录下,BLUETOOTH_MANAGER_SERVICE值为“bluetooth_manager”)。

代码位置:frameworks\base\services\java\com\android\server\SystemServer.java

  
  
  • 1
  • 2
    if (SystemProperties.get("ro.kernel.qemu").equals("1")) {
        Slog.i(TAG, "No Bluetooh Service (emulator)");
    } else if (factoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
        Slog.i(TAG, "No Bluetooth Service (factory test)");
    } else if (!context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH)) {
        Slog.i(TAG, "No Bluetooth Service (Bluetooth Hardware Not Present)");
    } else if (disableBluetooth) {
        Slog.i(TAG, "Bluetooth Service disabled by config");
    } else {
        Slog.i(TAG, "Bluetooth Manager Service");
        bluetooth = new BluetoothManagerService(context);
        ServiceManager.addService(BluetoothAdapter.BLUETOOTH_MANAGER_SERVICE, bluetooth);
    }
  
  

    我们先看一下BluetoothManagerService类的构造函数,代码比较多,我们主要看两个地方,loadStoredNameAndAddress()是读取蓝牙打开默认名称的地方,isBluetoothPersistedStateOn()是用来判断蓝牙是否已打开的,如果已打开,需要执行开启蓝牙的动作,前几行注册的广播其中就有这个作用。

    代码位置:frameworks\base\services\java\com\android\server\BluetoothManagerService.java
    
      
      
    • 1
    • 2
        BluetoothManagerService(Context context) {
            …一些变量声明初始化…
            IntentFilter filter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
            filter.addAction(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED);
            filter.addAction(Intent.ACTION_USER_SWITCHED);
            registerForAirplaneMode(filter);
            mContext.registerReceiver(mReceiver, filter);
            loadStoredNameAndAddress();
            if (isBluetoothPersistedStateOn()) {
                mEnableExternal = true;
            }
        }
      
      

      上面就完成了蓝牙的系统服务注册工作,如果没有设置蓝牙打开,系统也不会打开蓝牙,后面如果需要用到蓝牙服务只需通过systemServer的getServer方法即可。

      现在回到用户真正能接触到的界面开关部分,蓝牙界面开关就是Setting界面中的蓝牙开关,其实际就是调用BluetoothEnabler.java这个类了,BluetoothEnabler类是实现
      CompoundButton.OnCheckedChangeListener按键监听器,看到其onCheckedChanged方法,当按键按下时会跳入该方法,在该方法中首先判断是否开启了飞行模式,如果没则调用mLocalAdapter(LocalBluetoothAdapter)setBluetoothEnabled()方法,执行具体的开关动作。

      代码位置:packages\apps\Settings\src\com\android\settings\bluetooth\BluetoothEnabler.java
      
        
        
      • 1
      • 2
          public final class BluetoothEnabler implements CompoundButton.OnCheckedChangeListener {
              public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                  // Show toast message if Bluetooth is not allowed in airplane mode
                  if (isChecked && !WirelessSettings.isRadioAllowed(mContext, Settings.Global.RADIO_BLUETOOTH)) {
                      Toast.makeText(mContext, R.string.wifi_in_airplane_mode, Toast.LENGTH_SHORT).show();
                      // Reset switch to off
                      buttonView.setChecked(false);
                  }
                  if (mLocalAdapter != null) {
                      mLocalAdapter.setBluetoothEnabled(isChecked);
                  }
                  mSwitch.setEnabled(false);
              }
          }
        
        

        在LocalBluetoothAdapter类的setBluetoothEnabled方法中,根据是否打开再调用mAdapter(BluetoothAdapter)的enable或disable方法。并更新蓝牙状态机。

        代码位置:packages\apps\Settings\src\com\android\settings\bluetooth\LocalBluetoothAdapter.java
        
          
          
        • 1
        • 2
            public void setBluetoothEnabled(boolean enabled) {
                boolean success = enabled
                        ? mAdapter.enable()
                        : mAdapter.disable();
                if (success) {
                    setBluetoothStateInt(enabled
                        ? BluetoothAdapter.STATE_TURNING_ON
                        : BluetoothAdapter.STATE_TURNING_OFF);
                } else {
                    if (Utils.V) {
                        Log.v(TAG, "setBluetoothEnabled call, manager didn't return " +
        "success for enabled: " + enabled);
                    }
                    syncBluetoothState();
                }
            }
          
          

          请注意:这时候代码已经跳转到了framework层了。

          在BluetoothAdapter类中可以看到一个单例模式的应用,主要提供给其它程序调用蓝牙的一些方法用的,外部程序想调用蓝牙的方法就要先用这个拿到BluetoothAdapter对象,代码也简单看下吧,里面是典型的binder应用。就是前面在SystemServer中注册的蓝牙服务。

          代码位置:frameworks\base\core\java\android\bluetooth\BluetoothAdapter.java
          
            
            
          • 1
          • 2
              public static synchronized BluetoothAdapter getDefaultAdapter() {
                  if (sAdapter == null) {
                      IBinder b = ServiceManager.getService(BLUETOOTH_MANAGER_SERVICE);
                      if (b != null) {
                          IBluetoothManager managerService = IBluetoothManager.Stub.asInterface(b);
                          sAdapter = new BluetoothAdapter(managerService);
                      } else {
                          Log.e(TAG, "Bluetooth binder is null");
                      }
                  }
                  return sAdapter;
              }
            
            

            此时我们更关心mAdapter.enable()的后续操作,外部其它应用到getDefaultAdapter()也是调用enable(),注意,到了BluetoothAdapter我们已经在framework层了,顺着BluetoothAdapter.java的enable()调用,其先判断蓝牙是否已经打开,如果没打开则调用mManagerService(IBluetoothManager)的enable方法。

            代码位置:frameworks\base\core\java\android\bluetooth\BluetoothAdapter.java
            
              
              
            • 1
            • 2
                public boolean enable() {
                    if (isEnabled() == true){
                        if (DBG) Log.d(TAG, "enable(): BT is already enabled..!");
                        return true;
                    }
                    try {
                        return mManagerService.enable();
                    } catch (RemoteException e) {Log.e(TAG, "", e);}
                    return false;
                }
              
              

              IBluetoothManager类是Android进程间通信的接口,在其中定义了一堆的接口,一般这种远程服务对应的类名就是 BluetoothManagerService 类,主要用于调用在SystemServer中注册的蓝牙服务。在BluetoothAdapter类的构造函数中,将mManagerService绑定到了ServiceManager.getService(BLUETOOTH_MANAGER_SERVICE)的蓝牙服务中。我们直接进入BluetoothManagerService类的enable()方法。

              代码位置:frameworks\base\core\java\android\bluetooth\BluetoothAdapter.java
              
                
                
              • 1
              • 2
                  interface IBluetoothManager {
                      IBluetooth registerAdapter(in IBluetoothManagerCallback callback);
                      void unregisterAdapter(in IBluetoothManagerCallback callback);
                      void registerStateChangeCallback(in IBluetoothStateChangeCallback callback);
                      void unregisterStateChangeCallback(in IBluetoothStateChangeCallback callback);
                      boolean isEnabled();
                      boolean enable();
                      boolean enableNoAutoConnect();
                      boolean disable(boolean persist);
                      IBluetoothGatt getBluetoothGatt();
                      String getAddress();
                      String getName();
                  }
                
                

                在BluetoothManagerService类的enable()方法中,第一个if看到log那就知道如果enable正常就不会走,第二个if是打印调试信息,在后面的synchronized函数体中,实际有用的是sendEnableMsg(false)方法,跳到sendEnableMsg中。

                代码位置:frameworks\base\services\java\com\android\server\BluetoothManagerService.java
                
                  
                  
                • 1
                • 2
                    public boolean enable() {
                        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
                            long callingIdentity = Binder.clearCallingIdentity();
                            persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH);
                            Binder.restoreCallingIdentity(callingIdentity);
                            sendEnableMsg(false);
                        }
                        return true;
                    }
                  
                  

                  可以看到在sendEnableMsg中向系统发送了一条MESSAGE_ENABLE消息,再跳转到mHandler(BluetoothHandler)类的handleMessage方法,可以看到在handleMessage中有对MESSAGE_ENABLE消息的处理函数,实际的话就是调用了BluetoothManagerService类的handleEnable方法。

                  代码位置:frameworks\base\services\java\com\android\server\BluetoothManagerService.java
                  
                    
                    
                  • 1
                  • 2
                      private class BluetoothHandler extends Handler {
                          ...
                          @Override
                          public void handleMessage(Message msg) {
                              if (DBG) Log.d (TAG, "Message: " + msg.what);
                              switch (msg.what) {
                                  case MESSAGE_ENABLE:
                                      if (DBG) {
                                          Log.d(TAG, "MESSAGE_ENABLE: mBluetooth = " + mBluetooth);
                                      }
                                      mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE);
                                      mEnable = true;
                                      handleEnable(msg.arg1 == 1);
                                      break;
                                  }
                              }
                          }
                      }
                    
                    

                    handleEnable方法比较长,看到注释说明//Enable bluetooth,我们直接看这部分代码,实际执行的是mBluetooth.enable(),又是一个接口IBluetooth

                    代码位置:frameworks\base\services\java\com\android\server\BluetoothManagerService.java
                    
                      
                      
                    • 1
                    • 2
                        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());
                                    if (!doBind(i, mConnection,Context.BIND_AUTO_CREATE, 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);
                                    }
                                }
                            }
                        }
                      
                      

                      mBluetooth(IBluetooth)这个接口到底是对应哪个远程服务呢?在同一个目录下搜索,先搜索mBluetooth在哪里赋值了,搜索完BluetoothManagerService.java只在handleMessage中找到了mBluetooth = IBluetooth.Stub.asInterface(service),而IBinder service = (IBinder) msg.obj。也就是远程服务是发送“MESSAGE_BLUETOOTH_SERVICE_CONNECTED”消息对象。继续在BluetoothManagerService类中搜索是谁发送这条消息。

                      代码位置:frameworks\base\services\java\com\android\server\BluetoothManagerService.java
                      
                        
                        
                      • 1
                      • 2
                          private class BluetoothHandler extends Handler {
                              ...
                              @Override
                              public void handleMessage(Message msg) {
                                  if (DBG) Log.d (TAG, "Message: " + msg.what);
                                  switch (msg.what) {
                                      case MESSAGE_BLUETOOTH_SERVICE_CONNECTED:
                                      {
                                          if (DBG) Log.d(TAG,"MESSAGE_BLUETOOTH_SERVICE_CONNECTED: " + msg.arg1);
                                          IBinder service = (IBinder) msg.obj;
                                          synchronized(mConnection) {
                                              if (msg.arg1 == SERVICE_IBLUETOOTHGATT) {
                                                  mBluetoothGatt = IBluetoothGatt.Stub.asInterface(service);
                                                  break;
                                              } // else must be SERVICE_IBLUETOOTH
                                              //Remove timeout
                                              mHandler.removeMessages(MESSAGE_TIMEOUT_BIND);
                                              mBinding = false;
                                              mBluetooth = IBluetooth.Stub.asInterface(service);
                                              ...
                                          break;
                                      }
                                  }
                              }
                          }
                        
                        

                        BluetoothManagerService.java中发现在onServiceConnected方法中构建了该消息,并将调用该方法的service赋值给msg.obj,到底谁调用了这个函数呢,尝试搜索了下“onServiceConnected”并没有得到想要的结果,再回到onServiceConnected方法中,可以看到有个log,"BluetoothServiceConnection: " + className.getClassName(),就是说将BluetoothServiceConnection连接到一个服务上,在看到下面的if判断,最有可能的是连接到了AdapterService服务中。在Android 4.2 Bluetooth 分析总结(二) 蓝牙enable 的整个过程中作者从实际打印的log中也指出了在这一步系统会跳转到AdapterService。
                        D/BluetoothManagerService( 1646): BluetoothServiceConnection: connected to AdapterService

                        代码位置:frameworks\base\services\java\com\android\server\BluetoothManagerService.java
                        
                          
                          
                        • 1
                        • 2
                                public void onServiceConnected(ComponentName className, IBinder service) {
                                    if (DBG) Log.d(TAG, "BluetoothServiceConnection: " + className.getClassName());
                                    Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_CONNECTED);
                                    // TBD if (className.getClassName().equals(IBluetooth.class.getName())) {
                                    if (className.getClassName().equals("com.android.bluetooth.btservice.AdapterService")) {
                                        msg.arg1 = SERVICE_IBLUETOOTH;
                                        // } else if (className.getClassName().equals(IBluetoothGatt.class.getName())) {
                                    } else if (className.getClassName().equals("com.android.bluetooth.gatt.GattService")) {
                                        msg.arg1 = SERVICE_IBLUETOOTHGATT;
                                    } else {
                                        Log.e(TAG, "Unknown service connected: " + className.getClassName());
                                        return;
                                    }
                                    msg.obj = service;
                                    mHandler.sendMessage(msg);
                                }
                          
                          

                          这时代码从framework层跳到了APP层,符合了android代码架构图中的定义。

                          我们看到AdapterService的enable方法,可以发现在AdapterService类中有三个enable函数,从framework层到这到底调用了哪个enable函数呢,根据代码注释和实际情况,应该是调用了在AdapterServiceBinder类中的enable方法,在该方法中调用了service.enable(),而service是通过getService()方法获取的,看到该方法,实际是返回了mService(AdapterService),也就是调用了boolean enable()方法,最终调用了public synchronized boolean enable(boolean quietMode)方法。在这个方法中主要是构建了一个AdapterState.USER_TURN_ON消息,并发送给状态机mAdapterStateMachine去处理。

                          代码位置:packages\apps\Bluetooth\src\com\android\bluetooth\btservice\AdapterService.java
                          
                            
                            
                          • 1
                          • 2
                              public class AdapterService extends Service {
                                  ...
                                  private static class AdapterServiceBinder extends IBluetooth.Stub {
                                      private AdapterService mService;
                                      public AdapterServiceBinder(AdapterService svc) {
                                          mService = svc;
                                      }
                                  ...
                                      public boolean enable() {
                                          if ((Binder.getCallingUid() != Process.SYSTEM_UID) &&
                                              (!Utils.checkCaller())) {
                                              Log.w(TAG,"enable(): not allowed for non-active user and non system user");
                                              return false;
                                          }
                                          AdapterService service = getService();
                                          if (service == null) return false;
                                          return service.enable();
                                      }
                                  ...
                                      public AdapterService getService() {
                                          if (mService  != null && mService.isAvailable()) {
                                              return mService;
                                          }
                                          return null;
                                      }
                                  }
                                  ...
                                  //----API Methods--------
                                  ...
                                  boolean enable() {
                                      return enable (false);
                                  }   
                                  ...
                                  public synchronized boolean enable(boolean quietMode) {
                                      enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
                                                                      "Need BLUETOOTH ADMIN permission");
                                      if (DBG)debugLog("Enable called with quiet mode status =  " + mQuietmode);
                                      mQuietmode  = quietMode;
                                      Message m =
                                               mAdapterStateMachine.obtainMessage(AdapterState.USER_TURN_ON);
                                      mAdapterStateMachine.sendMessage(m);
                                      return true;
                                  }
                              }
                            
                            

                            这里用到了状态机的概念,在网上查了下有关Android蓝牙状态机的资料,没有找到合适的,大多是Android4.2之前的状态机分析,通过查看源码,在AdapterState状态机的注释中可以发现如下说明,说明该状态机有三个状态,分别是OnState、OffState以及PendingCommandState,再根据注释,在初始状态下,蓝牙应该处于OffState,中间态是PendingCommandState,正在打开是OnState。具体没有深入去分析代码,可能有错误,暂时按照这个流程继续进行蓝牙enable分析。

                            代码位置:packages\apps\Bluetooth\src\com\android\bluetooth\btservice\AdapterState.java
                            
                              
                              
                            • 1
                            • 2
                                /**
                                 * This state machine handles Bluetooth Adapter State.
                                 * States:
                                 *      {@link OnState} : Bluetooth is on at this state
                                 *      {@link OffState}: Bluetooth is off at this state. This is the initial
                                 *      state.
                                 *      {@link PendingCommandState} : An enable / disable operation is pending.
                                 * TODO(BT): Add per process on state.
                                 */
                              
                              

                              我们重点看状态机的消息处理部分,由于这时候进行的是蓝牙开启操作,状态机处于OffState状态下,在OffState的processMessage中找到对USER_TURN_ON的处理函数,前面的几个是进行状态机的状态更新,最后调用了adapterService.processStart(),我们跳进去看。

                              代码位置:packages\apps\Bluetooth\src\com\android\bluetooth\btservice\AdapterState.java
                              
                                
                                
                              • 1
                              • 2
                                  final class AdapterState extends StateMachine {
                                      ...
                                      private class OffState extends State {
                                          ...
                                          @Override
                                          public boolean processMessage(Message msg) {
                                              AdapterService adapterService = mAdapterService;
                                              if (adapterService == null) {
                                                  Log.e(TAG,"receive message at OffState after cleanup:" +
                                                            msg.what);
                                                  return false;
                                              }
                                              switch(msg.what) {
                                                 case USER_TURN_ON:
                                                     if (DBG) Log.d(TAG,"CURRENT_STATE=OFF, MESSAGE = USER_TURN_ON");
                                                     notifyAdapterStateChange(BluetoothAdapter.STATE_TURNING_ON);
                                                     mPendingCommandState.setTurningOn(true);
                                                     transitionTo(mPendingCommandState);
                                                     sendMessageDelayed(START_TIMEOUT, START_TIMEOUT_DELAY);
                                                     adapterService.processStart();
                                                     break;
                                              ...
                                              }
                                              return true;
                                          }
                                      }
                                      ...
                                  }
                                
                                

                                又回到了AdapterService,通过看给出的log提示以及函数名称,大概是进行了所有profile的状态机状态开启设置,在最后一个else中的log中也是显示processStart(): Profile Services alreay started,最后又调用状态机执行AdapterState.STARTED消息,执行mAdapterStateMachine.sendMessage(mAdapterStateMachine.obtainMessage(AdapterState.STARTED))

                                代码位置:packages\apps\Bluetooth\src\com\android\bluetooth\btservice\AdapterService.java
                                
                                  
                                  
                                • 1
                                • 2
                                   void processStart() {
                                        if (DBG) debugLog("processStart()");
                                        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);
                                        if (DBG) {debugLog("processStart(): Make Bond State Machine");}
                                        mBondStateMachine = BondStateMachine.make(this, mAdapterProperties, mRemoteDevices);
                                        mJniCallbacks.init(mBondStateMachine,mRemoteDevices);
                                        //FIXME: Set static instance here???
                                        setAdapterService(this);
                                        //Start profile services
                                        if (!mProfilesStarted && supportedProfileServices.length >0) {
                                            //Startup all profile services
                                            setProfileServiceState(supportedProfileServices,BluetoothAdapter.STATE_ON);
                                        }else {
                                            if (DBG) {debugLog("processStart(): Profile Services alreay started");}
                                            mAdapterStateMachine.sendMessage(mAdapterStateMachine.obtainMessage(AdapterState.STARTED));
                                        }
                                    }
                                  
                                  

                                  再次回到AdapterState类,由于这时候状态机处于pending状态下,所以在PendingCommandState中对该消息进行处理,实际是调用了adapterService.enableNative()方法,也就是终于通过JNI开始向下层调用底层操作方法进行蓝牙Enable操作。

                                  代码位置:packages\apps\Bluetooth\src\com\android\bluetooth\btservice\AdapterState.java
                                  
                                    
                                    
                                  • 1
                                  • 2
                                      final class AdapterState extends StateMachine {
                                          ...
                                          private class PendingCommandState extends State {
                                              private boolean mIsTurningOn;
                                              private boolean mIsTurningOff;
                                              ...
                                              @Override
                                              public boolean processMessage(Message msg) {
                                                  ...
                                                  switch(msg.what) {
                                                      case STARTED:   
                                                          if (DBG) Log.d(TAG,"CURRENT_STATE=PENDING, MESSAGE = STARTED, isTurningOn=" + isTurningOn + ", isTurningOff=" + isTurningOff);
                                                          //Remove start timeout
                                                          removeMessages(START_TIMEOUT);
                                                          //Enable
                                                          boolean ret = adapterService.enableNative();
                                                          if (!ret) {
                                                              Log.e(TAG, "Error while turning Bluetooth On");
                                                              notifyAdapterStateChange(BluetoothAdapter.STATE_OFF);
                                                              transitionTo(mOffState);
                                                          } else {
                                                              sendMessageDelayed(ENABLE_TIMEOUT, ENABLE_TIMEOUT_DELAY);
                                                          }
                                                          break;
                                                  ...
                                                  }
                                                  return true;
                                              }
                                          }
                                          ...
                                      }
                                    
                                    

                                    这里已经通过JNI从APP framework层进入了bluedroid协议栈了。

                                    根据Android JNI层的命名规则,找到了com_android_bluetooth_btservice_AdapterService.cpp,看到其中的enableNative()方法。实际是调用了sBluetoothInterface(bt_interface_t)的enable方法。sBluetoothInterface这个又是一个接口,在网上看别人写的博客说不能跳转,但是我这边可以直接跳转到bt_interface_t的定义,如果不能跳转依然可以到这个文章中看如何跳转Android 4.2 Bluetooth 分析总结(二) 蓝牙enable 的整个过程

                                    代码位置:packages\apps\Bluetooth\jni\com_android_bluetooth_btservice_AdapterService.cpp
                                    
                                      
                                      
                                    • 1
                                    • 2
                                        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) ? JNI_TRUE : JNI_FALSE;
                                            return result;
                                        }
                                      
                                      

                                      可以看出,在这个结构体中包含了大量的接口,有bluetooth.h自然有bluetooth.c文件,我们跳转到bluetooth.c中看下接口的具体实现。

                                      代码位置:hardware\libhardware\include\hardware\bluetooth.h
                                      
                                        
                                        
                                      • 1
                                      • 2
                                          /** Represents the standard Bluetooth DM interface. */
                                          typedef struct {
                                              /** set to sizeof(bt_interface_t) */
                                              size_t size;
                                              /**
                                               * Opens the interface and provides the callback routines
                                               * to the implemenation of this interface.
                                               */
                                              int (*init)(bt_callbacks_t* callbacks );
                                              /** Enable Bluetooth. */
                                              int (*enable)(void);
                                              /** Disable Bluetooth. */
                                              int (*disable)(void);
                                              ...
                                          } bt_interface_t;
                                        
                                        

                                        终于开始了最喜欢的c代码了,c代码看起来就轻松多了。

                                        在这里可以看到bluetooth.c实例化了一个bt_interface_t对象,bluetoothInterface。跳转到enable函数中,在打印了一个log信息后,先会对接口进行检查,如果接口ready就调用btif_enable_bluetooth()方法。

                                        代码位置:external\bluetooth\bluedroid\btif\src\bluetooth.c
                                        
                                          
                                          
                                        • 1
                                        • 2
                                            static int enable( void )
                                            {
                                                ALOGI("enable");
                                                /* sanity check */
                                                if (interface_ready() == FALSE)
                                                    return BT_STATUS_NOT_READY;
                                                return btif_enable_bluetooth();
                                            }
                                            ...
                                            static const bt_interface_t bluetoothInterface = {
                                                sizeof(bluetoothInterface),
                                                init,
                                                enable,
                                                disable,
                                                cleanup,
                                                get_adapter_properties,
                                                get_adapter_property,
                                                set_adapter_property,
                                                get_remote_device_properties,
                                                get_remote_device_property,
                                                set_remote_device_property,
                                                get_remote_service_record,
                                                get_remote_services,
                                                start_discovery,
                                                cancel_discovery,
                                                create_bond,
                                                remove_bond,
                                                cancel_bond,
                                                pin_reply,
                                                ssp_reply,
                                                get_profile_interface,
                                                dut_mode_configure,
                                                dut_mode_send,
                                            #if BLE_INCLUDED == TRUE
                                                le_test_mode,
                                            #else
                                                NULL,
                                            #endif
                                                config_hci_snoop_log
                                            };
                                          
                                          

                                          到了这一步基本上已经完成了上层的一堆蓝牙Enable代码分析,后面的都是bluedroid的代码了,具体到蓝牙的实际开关又涉及到各个厂商Vendor的设计。下面简要写一些后续的蓝牙Enable过程。

                                          一下就跳转到了btif_core.c中了,前面是一堆的判断以及状态机的设置,我们直接看到后面,又调用了bte_main_enable(),跳进去继续看。

                                          代码位置:external\bluetooth\bluedroid\btif\src\btif_core.c
                                          
                                            
                                            
                                          • 1
                                          • 2
                                              bt_status_t btif_enable_bluetooth(void)
                                              {
                                                  BTIF_TRACE_DEBUG0("BTIF ENABLE BLUETOOTH");
                                                  if (btif_core_state != BTIF_CORE_STATE_DISABLED)
                                                  {
                                                      ALOGD("not disabled\n");
                                                      return BT_STATUS_DONE;
                                                  }
                                                  btif_core_state = BTIF_CORE_STATE_ENABLING;
                                                  /* Create the GKI tasks and run them */
                                                  bte_main_enable();
                                                  return BT_STATUS_SUCCESS;
                                              }
                                            
                                            

                                            认真看下这个函数,首先初始化了BTE的控制块,是什么呢,大概看了下,主要是一些参数设置。主要看到bte_hci_enable(),这个函数比较长,首先启动了一个preload定时器,主要用于重新打开蓝牙的操作,以防蓝牙长时间没有打开,先不管,继续往下看,bt_hc_if(bt_hc_interface_t)是什么东西呢,我们跳进去看看,bte_hci_enable()的分析后面继续开展,先看看bt_hc_if(bt_hc_interface_t)是什么东西,后面很多地方都有调用。

                                            代码位置:external\bluetooth\bluedroid\main\bte_main.c
                                            
                                              
                                              
                                            • 1
                                            • 2
                                                void bte_main_enable()
                                                {
                                                    APPL_TRACE_DEBUG1("%s", __FUNCTION__);
                                                    /* Initialize BTE control block */
                                                    BTE_Init();
                                                    lpm_enabled = FALSE;
                                                    bte_hci_enable();
                                                    GKI_create_task((TASKPTR)btu_task, BTU_TASK, BTE_BTU_TASK_STR,
                                                                    (UINT16 *) ((UINT8 *)bte_btu_stack + BTE_BTU_STACK_SIZE),
                                                                    sizeof(bte_btu_stack));
                                                    GKI_run(0);
                                                }
                                                ...
                                                static void bte_hci_enable(void)
                                                {
                                                    APPL_TRACE_DEBUG1("%s", __FUNCTION__);
                                                    preload_start_wait_timer();
                                                    if (bt_hc_if)
                                                    {
                                                        int result = bt_hc_if->init(&hc_callbacks, btif_local_bd_addr.address);
                                                        APPL_TRACE_EVENT1("libbt-hci init returns %d", result);
                                                        assert(result == BT_HC_STATUS_SUCCESS);
                                                        if (hci_logging_enabled == TRUE || hci_logging_config == TRUE)
                                                            bt_hc_if->logging(BT_HC_LOGGING_ON, hci_logfile);
                                                #if (defined (BT_CLEAN_TURN_ON_DISABLED) && BT_CLEAN_TURN_ON_DISABLED == TRUE)
                                                        APPL_TRACE_DEBUG1("%s  Not Turninig Off the BT before Turninig ON", __FUNCTION__);
                                                        /* Do not power off the chip before powering on  if BT_CLEAN_TURN_ON_DISABLED flag
                                                         is defined and set to TRUE to avoid below mentioned issue.
                                                         Wingray kernel driver maintains a combined  counter to keep track of
                                                         BT-Wifi state. Invoking  set_power(BT_HC_CHIP_PWR_OFF) when the BT is already
                                                         in OFF state causes this counter to be incorrectly decremented and results in undesired
                                                         behavior of the chip.
                                                         This is only a workaround and when the issue is fixed in the kernel this work around
                                                         should be removed. */
                                                #else
                                                        /* toggle chip power to ensure we will reset chip in case
                                                           a previous stack shutdown wasn't completed gracefully */
                                                        bt_hc_if->set_power(BT_HC_CHIP_PWR_OFF);
                                                #endif
                                                        bt_hc_if->set_power(BT_HC_CHIP_PWR_ON);
                                                        bt_hc_if->preload(NULL);
                                                    }
                                                }
                                              
                                              

                                              bt_hc_interface_t和前面的bt_interface_t接口一样,根据其说明文件,其是Bluetooth Host/Controller Interface。这个接口的实现在哪呢,看到目录,我们在src目录找找,也可以对整个project进行检索,很快我们发现了对该接口的实现。

                                              代码位置:external\bluetooth\bluedroid\hci\include\bt_hci_lib.h
                                              
                                                
                                                
                                              • 1
                                              • 2
                                                  /*
                                                   * Bluetooth Host/Controller Interface
                                                   */
                                                  typedef struct {
                                                      /** Set to sizeof(bt_hc_interface_t) */
                                                      size_t          size;
                                                      /**
                                                       * Opens the interface and provides the callback routines
                                                       * to the implemenation of this interface.
                                                       */
                                                      int   (*init)(const bt_hc_callbacks_t* p_cb, unsigned char *local_bdaddr);
                                                      /** Chip power control */
                                                      void (*set_power)(bt_hc_chip_power_state_t state);
                                                      /** Set low power mode wake */
                                                      int   (*lpm)(bt_hc_low_power_event_t event);
                                                      /** Called prior to stack initialization */
                                                      void (*preload)(TRANSAC transac);
                                                      /** Called post stack initialization */
                                                      void (*postload)(TRANSAC transac);
                                                      /** Transmit buffer */
                                                      int (*transmit_buf)(TRANSAC transac, char *p_buf, int len);
                                                      /** Controls receive flow */
                                                      int (*set_rxflow)(bt_rx_flow_state_t state);
                                                      /** Controls HCI logging on/off */
                                                      int (*logging)(bt_hc_logging_state_t state, char *p_path);
                                                      /** Closes the interface */
                                                      void  (*cleanup)( void );
                                                  } bt_hc_interface_t;
                                                
                                                

                                                bt_hc_interface_t接口在bt_hci_bdroid.c中有具体实现,现在再次回到bte_hci_enable()

                                                代码位置:external\bluetooth\bluedroid\hci\src\bt_hci_bdroid.c
                                                
                                                  
                                                  
                                                • 1
                                                • 2
                                                    static const bt_hc_interface_t bluetoothHCLibInterface = {
                                                        sizeof(bt_hc_interface_t),
                                                        init,
                                                        set_power,
                                                        lpm,
                                                        preload,
                                                        postload,
                                                        transmit_buf,
                                                        set_rxflow,
                                                        logging,
                                                        cleanup
                                                    };
                                                  
                                                  

                                                  首先调用了bt_hc_if的init函数,根据注释,init函数主要用来打开interface并且提供回调机制,我们跳进去看下。

                                                  代码位置:external\bluetooth\bluedroid\main\bte_main.c
                                                  
                                                    
                                                    
                                                  • 1
                                                  • 2
                                                      static void bte_hci_enable(void)
                                                      {
                                                          APPL_TRACE_DEBUG1("%s", __FUNCTION__);
                                                          preload_start_wait_timer();
                                                          if (bt_hc_if)
                                                          {
                                                              int result = bt_hc_if->init(&hc_callbacks, btif_local_bd_addr.address);
                                                              APPL_TRACE_EVENT1("libbt-hci init returns %d", result);
                                                              assert(result == BT_HC_STATUS_SUCCESS);
                                                              if (hci_logging_enabled == TRUE || hci_logging_config == TRUE)
                                                                  bt_hc_if->logging(BT_HC_LOGGING_ON, hci_logfile);
                                                      #if (defined (BT_CLEAN_TURN_ON_DISABLED) && BT_CLEAN_TURN_ON_DISABLED == TRUE)
                                                              APPL_TRACE_DEBUG1("%s  Not Turninig Off the BT before Turninig ON", __FUNCTION__);
                                                              /* Do not power off the chip before powering on  if BT_CLEAN_TURN_ON_DISABLED flag
                                                               is defined and set to TRUE to avoid below mentioned issue.
                                                               Wingray kernel driver maintains a combined  counter to keep track of
                                                               BT-Wifi state. Invoking  set_power(BT_HC_CHIP_PWR_OFF) when the BT is already
                                                               in OFF state causes this counter to be incorrectly decremented and results in undesired
                                                               behavior of the chip.
                                                               This is only a workaround and when the issue is fixed in the kernel this work around
                                                               should be removed. */
                                                      #else
                                                              /* toggle chip power to ensure we will reset chip in case
                                                                 a previous stack shutdown wasn't completed gracefully */
                                                              bt_hc_if->set_power(BT_HC_CHIP_PWR_OFF);
                                                      #endif
                                                              bt_hc_if->set_power(BT_HC_CHIP_PWR_ON);
                                                              bt_hc_if->preload(NULL);
                                                          }
                                                      }
                                                    
                                                    

                                                    我们都知道,蓝牙的话分为HostController,两者通过HCI层进行数据交互。Host的话是Android操作系统,这部分是通用的,由google公司提供;Controller的话是一个个芯片厂商提供的,这部分各个厂商都有其独立设计。在Android4.2后的bluedroid中将所有厂商的设计文件放在vendor目录中,而为了实现上层对芯片的操作,bluedroid提供了专门的接口,下面我们通过代码分析来了解bluedroid是怎么完成这些操作的。

                                                    这个init函数非常的长,首先看到第一个重要跳转就是init_vnd_if(local_bdaddr),从函数的字面理解就是调用厂商vender的init函数,在函数的注释中了解到这个函数主要完成vendor lib interface的初始化操作。

                                                    代码位置:external\bluetooth\bluedroid\hci\src\bt_hci_bdroid.c
                                                    
                                                      
                                                      
                                                    • 1
                                                    • 2
                                                        static int init(const bt_hc_callbacks_t* p_cb, unsigned char *local_bdaddr)
                                                        {
                                                            ...
                                                            /* store reference to user callbacks */
                                                            bt_hc_cbacks = (bt_hc_callbacks_t *) p_cb;
                                                            init_vnd_if(local_bdaddr);
                                                            ...
                                                        }
                                                      
                                                      

                                                      在这里完成了厂商定制功能与Android系统的绑定,系统后面都可以通过bt_vnd_if调用厂商的定制功能。在这里我们不深入分析厂商具体做了什么。

                                                      首先利用dlopen方法打开了libbt-vendor.so厂商的配置文件,并将动态库的句柄赋给dlhandle,再通过dlsym方法将"BLUETOOTH_VENDOR_LIB_INTERFACE"句柄返回给bt_vnd_if,关于libbt-vendor.so的介绍说明可以看android bluetooth 移植相关注意事项。在这里主要就是要厂商实现bt_vendor_interface_t这一通用接口,并且将接口赋值给bt_vnd_if,后面就可以通过bt_vnd_if实现对厂商定制功能的调用。最后再利用厂商实现的init方法实现蓝牙芯片的init操作(厂商具体决定init过程的具体操作)。

                                                      代码位置:external\bluetooth\bluedroid\hci\src\bt_hw.c
                                                      
                                                        
                                                        
                                                      • 1
                                                      • 2
                                                          void init_vnd_if(unsigned char *local_bdaddr)
                                                          {
                                                              void *dlhandle;
                                                              dlhandle = dlopen("libbt-vendor.so", RTLD_NOW);
                                                              if (!dlhandle)
                                                              {
                                                                  ALOGE("!!! Failed to load libbt-vendor.so !!!");
                                                                  return;
                                                              }
                                                              bt_vnd_if = (bt_vendor_interface_t *) dlsym(dlhandle, "BLUETOOTH_VENDOR_LIB_INTERFACE");
                                                              if (!bt_vnd_if)
                                                              {
                                                                  ALOGE("!!! Failed to get bt vendor interface !!!");
                                                                  return;
                                                              }
                                                              bt_vnd_if->init(&vnd_callbacks, local_bdaddr);
                                                          }
                                                        
                                                        

                                                        bt_vendor_lib.h的定义如下,可以看到dlsym方法返回的bt_vnd_if就是指向了bt_vendor_interface_t结构体。

                                                        代码位置:external\bluetooth\bluedroid\hci\include\bt_vendor_lib.h
                                                        
                                                          
                                                          
                                                        • 1
                                                        • 2
                                                            /*
                                                             * Bluetooth Host/Controller VENDOR Interface
                                                             */
                                                            typedef struct {
                                                                /** Set to sizeof(bt_vndor_interface_t) */
                                                                size_t          size;
                                                                /*
                                                                 * Functions need to be implemented in Vendor libray (libbt-vendor.so).
                                                                 */
                                                                /**
                                                                 * Caller will open the interface and pass in the callback routines
                                                                 * to the implemenation of this interface.
                                                                 */
                                                                int   (*init)(const bt_vendor_callbacks_t* p_cb, unsigned char *local_bdaddr);
                                                                /**  Vendor specific operations */
                                                                int (*op)(bt_vendor_opcode_t opcode, void *param);
                                                                /** Closes the interface */
                                                                void  (*cleanup)(void);
                                                            } bt_vendor_interface_t;
                                                            /*
                                                             * External shared lib functions/data
                                                             */
                                                            /* Entry point of DLib --
                                                             *      Vendor library needs to implement the body of bt_vendor_interface_t
                                                             *      structure and uses the below name as the variable name. HCI library
                                                             *      will use this symbol name to get address of the object through the
                                                             *      dlsym call.
                                                             */
                                                            extern const bt_vendor_interface_t BLUETOOTH_VENDOR_LIB_INTERFACE;
                                                          
                                                          

                                                          回到bt_hci_bdroid.c函数,在init_vnd_if方法中注册了厂商的hci接口,utils_init()初始化了一个互斥锁,暂不去管他,后面用到了#ifdef…#else…#endif的宏if语句,默认情况下,Android bluedroid是采用h4也就是uart传输方式,也就是其声明了一个hci_h4_func_table函数体,并将p_hci_if指向了该函数体,随后调用了hci_h4_func_table中的init函数。

                                                          代码位置:external\bluetooth\bluedroid\hci\src\bt_hci_bdroid.c
                                                          
                                                            
                                                            
                                                                static int init(const bt_hc_callbacks_t* p_cb, unsigned char *local_bdaddr)
                                                                {
                                                                    ...
                                                                    init_vnd_if(local_bdaddr);
                                                                    utils_init();
                                                                #ifdef HCI_USE_MCT
                                                                    extern tHCI_IF hci_mct_func_table;
                                                                    p_hci_if = &hci_mct_func_table;
                                                                #else
                                                                    extern tHCI_IF hci_h4_func_table;
                                                                    p_hci_if = &hci_h4_func_table;
                                                                #endif
                                                                    p_hci_if->init();
                                                                    ...
                                                                }
                                                              
                                                              

                                                              我们跳到hci_h4_func_table函数体重看看其具体干了什么,可以看到其定义了一个h4的服务接口,在hci_h4_init函数中奇首先初始化了一个队列h4_cb.acl_rx_q用于接收acl数据。然后设置了一些参数,最后init了btsnoop,也就是初始化了抓取蓝牙hci log的btsnoop,实际就是初始化了一个thread,具体就不跳进去了,代码在external\bluetooth\bluedroid\hci\src\btsnoop.c

                                                              代码位置:external\bluetooth\bluedroid\hci\src\hci_h4.c
                                                              
                                                                
                                                                
                                                                    void hci_h4_init(void)
                                                                    {
                                                                        HCIDBG("hci_h4_init");
                                                                        memset(&h4_cb, 0, sizeof(tHCI_H4_CB));
                                                                        utils_queue_init(&(h4_cb.acl_rx_q));
                                                                        /* Per HCI spec., always starts with 1 */
                                                                        num_hci_cmd_pkts = 1;
                                                                        /* Give an initial values of Host Controller's ACL data packet length
                                                                         * Will update with an internal HCI(_LE)_Read_Buffer_Size request
                                                                         */
                                                                        h4_cb.hc_acl_data_size = 1021;
                                                                        h4_cb.hc_ble_acl_data_size = 27;
                                                                        btsnoop_init();
                                                                    }
                                                                    /******************************************************************************
                                                                    **  HCI H4 Services interface table
                                                                    ******************************************************************************/
                                                                    const tHCI_IF hci_h4_func_table =
                                                                    {
                                                                        hci_h4_init,
                                                                        hci_h4_cleanup,
                                                                        hci_h4_send_msg,
                                                                        hci_h4_send_int_cmd,
                                                                        hci_h4_get_acl_data_length,
                                                                        hci_h4_receive_msg
                                                                    };
                                                                  
                                                                  

                                                                  bt_hc_worker_thread线程里面有很多重要的事件处理,可以具体看看。

                                                                  再次回到bt_hci_bdroid.c函数,在初始化hci后,其继续初始化了userial,也就是初始化了串口,这里需要根据前面的#ifdef来决定跳转到那个userial.c文件,文件位置在external\bluetooth\bluedroid\hci\src\userial.c。随后对lpm进行了初始化,在lpm_init函数中调用了芯片厂商中BT_VND_OP_GET_LPM_IDLE_TIMEOUT所对应的函数,然后赋值给bt_lpm_cb.timeout_ms,文件位置在external\bluetooth\bluedroid\hci\src\lmp.c。在utils_queue_init初始化了一个发送队列。在init函数最后创建了一个bt_hc_worker_thread蓝牙工作主线程,用于发送和接收命令。

                                                                  代码位置:external\bluetooth\bluedroid\hci\src\bt_hci_bdroid.c
                                                                  
                                                                    
                                                                    
                                                                  • 1
                                                                  • 2
                                                                      static int init(const bt_hc_callbacks_t* p_cb, unsigned char *local_bdaddr)
                                                                      {
                                                                          ...
                                                                          p_hci_if->init();
                                                                          userial_init();
                                                                          lpm_init();
                                                                          utils_queue_init(&tx_q);
                                                                          ...
                                                                          pthread_mutex_init(&hc_cb.mutex, NULL);
                                                                          pthread_cond_init(&hc_cb.cond, NULL);
                                                                          pthread_attr_init(&thread_attr);
                                                                          if (pthread_create(&hc_cb.worker_thread, &thread_attr, \
                                                                                             bt_hc_worker_thread, NULL) != 0)
                                                                          {
                                                                              ...
                                                                          }
                                                                          ...
                                                                          return BT_HC_STATUS_SUCCESS;
                                                                      }
                                                                    
                                                                    

                                                                    回到最初的bte_hci_enable()函数,上面就完成了bt_hc_if->init函数,然后根据是否需要打开hci log来打开hci log,后面的宏if语句用于判断是否已经打开蓝牙,如果没有则先关闭chip power bt_hc_if->set_power(BT_HC_CHIP_PWR_OFF)然后再打开chip power bt_hc_if->set_power(BT_HC_CHIP_PWR_ON)。最后调用了bt_hc_if->preload(NULL)函数,主要进行一些芯片的预操作,具体分析见后文。

                                                                    代码位置:external\bluetooth\bluedroid\main\bte_main.c
                                                                    
                                                                      
                                                                      
                                                                    • 1
                                                                    • 2
                                                                        static void bte_hci_enable(void)
                                                                        {
                                                                            APPL_TRACE_DEBUG1("%s", __FUNCTION__);
                                                                            preload_start_wait_timer();
                                                                            if (bt_hc_if)
                                                                            {
                                                                                int result = bt_hc_if->init(&hc_callbacks, btif_local_bd_addr.address);
                                                                                ...
                                                                                if (hci_logging_enabled == TRUE || hci_logging_config == TRUE)
                                                                                    bt_hc_if->logging(BT_HC_LOGGING_ON, hci_logfile);
                                                                        #if (defined (BT_CLEAN_TURN_ON_DISABLED) && BT_CLEAN_TURN_ON_DISABLED == TRUE)
                                                                                APPL_TRACE_DEBUG1("%s  Not Turninig Off the BT before Turninig ON", __FUNCTION__);
                                                                                /* Do not power off the chip before powering on  if BT_CLEAN_TURN_ON_DISABLED flag
                                                                                 is defined and set to TRUE to avoid below mentioned issue.
                                                                                 Wingray kernel driver maintains a combined  counter to keep track of
                                                                                 BT-Wifi state. Invoking  set_power(BT_HC_CHIP_PWR_OFF) when the BT is already
                                                                                 in OFF state causes this counter to be incorrectly decremented and results in undesired
                                                                                 behavior of the chip.
                                                                                 This is only a workaround and when the issue is fixed in the kernel this work around
                                                                                 should be removed. */
                                                                        #else
                                                                                /* toggle chip power to ensure we will reset chip in case
                                                                                   a previous stack shutdown wasn't completed gracefully */
                                                                                bt_hc_if->set_power(BT_HC_CHIP_PWR_OFF);
                                                                        #endif
                                                                                bt_hc_if->set_power(BT_HC_CHIP_PWR_ON);
                                                                                bt_hc_if->preload(NULL);
                                                                            }
                                                                        }
                                                                      
                                                                      

                                                                      找到bt_hc_interface_t接口在bt_hci_bdroid.cset_power()的具体实现,首先设置了power的状态,然后调用厂商接口bt_vnd_if中的BT_VND_OP_POWER_CTRL所对应的函数,执行芯片的上电操作。

                                                                      代码位置:external\bluetooth\bluedroid\hci\src\bt_hci_bdroid.c
                                                                      
                                                                        
                                                                        
                                                                      • 1
                                                                      • 2
                                                                          /** Chip power control */
                                                                          static void set_power(bt_hc_chip_power_state_t state)
                                                                          {
                                                                              int pwr_state;
                                                                              BTHCDBG("set_power %d", state);
                                                                              /* Calling vendor-specific part */
                                                                              pwr_state = (state == BT_HC_CHIP_PWR_ON) ? BT_VND_PWR_ON : BT_VND_PWR_OFF;
                                                                              if (bt_vnd_if)
                                                                                  bt_vnd_if->op(BT_VND_OP_POWER_CTRL, &pwr_state);
                                                                              else
                                                                                  ALOGE("vendor lib is missing!");
                                                                          }
                                                                        
                                                                        

                                                                        找到bt_hc_interface_t接口在bt_hci_bdroid.cpreload()的具体实现,其就是发送了一个事件,也就是向我们前面在bt_hci_bdroid.c创建的线程bt_hc_worker_thread发送了HC_EVENT_PRELOAD消息,我们跳到线程里对该消息的处理函数中,可以看到,其首先打开了串口userial_open(USERIAL_PORT_1),然后调用了vendor定义的BT_VND_OP_FW_CFG所对应的函数进行芯片framework的config操作。

                                                                        代码位置:external\bluetooth\bluedroid\hci\src\bt_hci_bdroid.c
                                                                        
                                                                          
                                                                          
                                                                        • 1
                                                                        • 2
                                                                            /** Called prio to stack initialization */
                                                                            static void preload(TRANSAC transac)
                                                                            {
                                                                                BTHCDBG("preload");
                                                                                bthc_signal_event(HC_EVENT_PRELOAD);
                                                                            }
                                                                            ...
                                                                            static void *bt_hc_worker_thread(void *arg)
                                                                            {
                                                                                ...
                                                                                while (lib_running)
                                                                                {
                                                                                    pthread_mutex_lock(&hc_cb.mutex);
                                                                                    while (ready_events == 0)
                                                                                    {
                                                                                        pthread_cond_wait(&hc_cb.cond, &hc_cb.mutex);
                                                                                    }
                                                                                    events = ready_events;
                                                                                    ready_events = 0;
                                                                                    pthread_mutex_unlock(&hc_cb.mutex);
                                                                                    ...
                                                                                    if (events & HC_EVENT_PRELOAD)
                                                                                    {
                                                                                        userial_open(USERIAL_PORT_1);
                                                                                        /* Calling vendor-specific part */
                                                                                        if (bt_vnd_if)
                                                                                        {
                                                                                            bt_vnd_if->op(BT_VND_OP_FW_CFG, NULL);
                                                                                        }
                                                                                        else
                                                                                        {
                                                                                            if (bt_hc_cbacks)
                                                                                                bt_hc_cbacks->preload_cb(NULL, BT_HC_PRELOAD_FAIL);
                                                                                        }
                                                                                    }
                                                                                    ...
                                                                                }
                                                                                ALOGI("bt_hc_worker_thread exiting");
                                                                                lib_running = 0;
                                                                                pthread_exit(NULL);
                                                                                return NULL;    // compiler friendly
                                                                            }
                                                                          
                                                                          

                                                                          userial_open中主要调用vendor定义的BT_VND_OP_USERIAL_OPEN所对应的函数进行userial的打开操作,然后再创建了一个串口读取线程userial_read_thread

                                                                          代码位置:external\bluetooth\bluedroid\hci\src\userial.c
                                                                          
                                                                            
                                                                            
                                                                          • 1
                                                                          • 2
                                                                              uint8_t userial_open(uint8_t port)
                                                                              {
                                                                                  ...
                                                                                  if (userial_running)
                                                                                  {
                                                                                      /* Userial is open; close it first */
                                                                                      userial_close();
                                                                                      utils_delay(50);
                                                                                  }
                                                                                  ...
                                                                                  /* Calling vendor-specific part */
                                                                                  if (bt_vnd_if)
                                                                                  {
                                                                                      result = bt_vnd_if->op(BT_VND_OP_USERIAL_OPEN, &fd_array);
                                                                                      ...
                                                                                  }
                                                                                  else
                                                                                  {
                                                                                      ALOGE("userial_open: missing vendor lib interface !!!");
                                                                                      ALOGE("userial_open: unable to open UART port");
                                                                                      return FALSE;
                                                                                  }
                                                                                  ...
                                                                                  if (pthread_create(&(userial_cb.read_thread), &thread_attr, \
                                                                                                     userial_read_thread, NULL) != 0 )
                                                                                  {
                                                                                      ALOGE("pthread_create failed!");
                                                                                      return FALSE;
                                                                                  }
                                                                                  ...
                                                                                  return TRUE;
                                                                              }
                                                                            
                                                                            

                                                                            到现在已经完成了bte_hci_enable的全部操作,回忆下,其首先绑定了蓝牙芯片厂商定制功能函数,首先调用了vendor芯片的init函数;然后根据实际需要,通过宏if语句绑定了hci函数体hci_h4_func_table,并调用其init函数进行hci的初始化;然后调用了userial和lpm的初始化,并创建了了用于蓝牙hc工作的主线程;接着进行了蓝牙的上电操作;最后进行了蓝牙的preload操作,包括打开userial,创建userial read线程,并执行蓝牙芯片的framework config操作。

                                                                            再次回到bte_main.c中的bte_main_enable()函数,其最后create了一个GKI任务,并启动了该任务。

                                                                            代码位置:external\bluetooth\bluedroid\main\bte_main.c
                                                                            
                                                                              
                                                                              
                                                                            • 1
                                                                            • 2
                                                                                void bte_main_enable()
                                                                                {
                                                                                    APPL_TRACE_DEBUG1("%s", __FUNCTION__);
                                                                                    /* Initialize BTE control block */
                                                                                    BTE_Init();
                                                                                    lpm_enabled = FALSE;
                                                                                    bte_hci_enable();
                                                                                    GKI_create_task((TASKPTR)btu_task, BTU_TASK, BTE_BTU_TASK_STR,
                                                                                                    (UINT16 *) ((UINT8 *)bte_btu_stack + BTE_BTU_STACK_SIZE),
                                                                                                    sizeof(bte_btu_stack));
                                                                                    GKI_run(0);
                                                                                }
                                                                              
                                                                              

                                                                              至此,蓝牙的enable操作的就全部结束了,文章中存在很多问题,欢迎大家的指正。

                                                                              评论
                                                                              添加红包

                                                                              请填写红包祝福语或标题

                                                                              红包个数最小为10个

                                                                              红包金额最低5元

                                                                              当前余额3.43前往充值 >
                                                                              需支付:10.00
                                                                              成就一亿技术人!
                                                                              领取后你会自动成为博主和红包主的粉丝 规则
                                                                              hope_wisdom
                                                                              发出的红包
                                                                              实付
                                                                              使用余额支付
                                                                              点击重新获取
                                                                              扫码支付
                                                                              钱包余额 0

                                                                              抵扣说明:

                                                                              1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
                                                                              2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

                                                                              余额充值