Android8.0 藍牙系統

Android 提供支持經典藍牙和藍牙低功耗的默認藍牙堆棧。藉助藍牙,Android 設備能夠建立我的區域網絡,以便經過附近的藍牙設備發送和接收數據,在 Android 4.3 及更高版本中,Android 藍牙堆棧可提供實現藍牙低功耗 (BLE) 的功能。要充分利用 BLE API,請遵循 Android 藍牙 HCI 要求。具備合格芯片組的 Android 設備能夠實現經典藍牙或同時實現經典藍牙和 BLE。BLE 不能向後兼容較舊版本的藍牙芯片組。在 Android 8.0 中,原生藍牙堆棧徹底符合藍牙 5 的要求。要使用可用的藍牙 5 功能,該設備須要具備符合藍牙 5 要求的芯片組。
java

處於應用框架級別的是應用代碼,它使用 android.bluetooth API 與藍牙硬件進行交互。此代碼在內部經過 Binder IPC 機制調用藍牙進程。藍牙系統服務(位於 packages/apps/Bluetooth 中)被打包爲 Android 應用,並在 Android 框架層實現藍牙服務和配置文件。此應用經過 JNI 調用原生藍牙堆棧。與 android.bluetooth 相關聯的 JNI 代碼位於 packages/apps/Bluetooth/jni 中。當發生特定藍牙操做時(例如發現設備時),JNI 代碼會調用藍牙堆棧。系統在 AOSP 中提供了默認藍牙堆棧,它位於 system/bt 中。該堆棧會實現常規藍牙 HAL,並經過擴展程序和更改配置對其進行自定義。供應商設備使用硬件接口設計語言 (HIDL) 與藍牙堆棧交互。HIDL 定義了藍牙堆棧和供應商實現之間的接口。要生成藍牙 HIDL 文件,請將藍牙接口文件傳遞到 HIDL 生成工具中。接口文件位於 hardware/interfaces/bluetooth 下。Android 8.0 藍牙堆棧是一個徹底限定的藍牙堆棧。限定列表位於藍牙 SIG 網站上的 QDID 97584 下。核心藍牙堆棧位於 system/bt 下。
1. 藍牙管理服務android

frameworks\base\core\java\android\bluetooth\BluetoothProfile.java
藍牙配置文件均實現了BluetoothProfile接口git

public interface BluetoothProfile { .......
             public interface ServiceListener {......} //回調接口
 } //接口網絡

frameworks\base\core\java\android\bluetooth\BluetoothHeadset.java
以BluetoothHeadset爲例, IBluetoothManager是AIDL文件,實現體爲BluetoothManagerServiceapp

 BluetoothHeadset(Context context, ServiceListener l) {
        mContext = context;
        mServiceListener = l; //上述的回調接口
        mAdapter = BluetoothAdapter.getDefaultAdapter();
        IBluetoothManager mgr = mAdapter.getBluetoothManager(); //做爲BluetoothAdapter的代理
        if (mgr != null) {
            try {
                //mBluetoothStateChangeCallback是一個IBluetoothStateChangeCallback
                //此回調主要處理來自BluetoothManagerService的藍牙狀態改變
                mgr.registerStateChangeCallback(mBluetoothStateChangeCallback); //註冊回調
            } catch (RemoteException e) {
                Log.e(TAG,"",e);
            }
        }框架

        doBind(); //綁定Profile
    }less

frameworks\base\core\java\android\bluetooth\BluetoothHeadset.java
向 BluetoothManagerService 註冊添加Profilesocket

 boolean doBind() {
        try {
            //mConnection的類型爲IBluetoothProfileServiceConnection
            return mAdapter.getBluetoothManager().bindBluetoothProfileService(
                    BluetoothProfile.HEADSET, mConnection);
        } catch (RemoteException e) {
            Log.e(TAG, "Unable to bind HeadsetService", e);
        }
        return false;
    }ide

frameworks\base\core\java\android\bluetooth\BluetoothHeadset.java
由BluetoothManagerService回調處理函數

private final IBluetoothProfileServiceConnection mConnection
            = new IBluetoothProfileServiceConnection.Stub()  {
        @Override
        public void onServiceConnected(ComponentName className, IBinder service) {
            if (DBG) Log.d(TAG, "Proxy object connected");
            //返回一個Service 類型爲 IBluetoothHeadset
            mService = IBluetoothHeadset.Stub.asInterface(Binder.allowBlocking(service));
            mHandler.sendMessage(mHandler.obtainMessage(
                    MESSAGE_HEADSET_SERVICE_CONNECTED));
        }
        @Override
        public void onServiceDisconnected(ComponentName className) {
            if (DBG) Log.d(TAG, "Proxy object disconnected");
            mService = null;
            mHandler.sendMessage(mHandler.obtainMessage(
                    MESSAGE_HEADSET_SERVICE_DISCONNECTED));
        }
    };

frameworks\base\core\java\android\bluetooth\BluetoothHeadset.java

 private final Handler mHandler = new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MESSAGE_HEADSET_SERVICE_CONNECTED: {
                    if (mServiceListener != null) {
                        //調用BluetoothProfile的回調函數
                        mServiceListener.onServiceConnected(BluetoothProfile.HEADSET,
                                BluetoothHeadset.this);
                    }
                    break;
                }
                case MESSAGE_HEADSET_SERVICE_DISCONNECTED: {
                    if (mServiceListener != null) {
                        mServiceListener.onServiceDisconnected(BluetoothProfile.HEADSET);
                    }
                    break;
                }
            }
        }
    };

frameworks\base\services\core\java\com\android\server\BluetoothManagerService.java
向BluetoothManagerService註冊狀態回調

  public void registerStateChangeCallback(IBluetoothStateChangeCallback callback) {
        //交給BluetoothHandler(內部類)處理
        Message msg = mHandler.obtainMessage(MESSAGE_REGISTER_STATE_CHANGE_CALLBACK);
        msg.obj = callback;
        mHandler.sendMessage(msg);
    }

frameworks\base\services\core\java\com\android\server\BluetoothManagerService.java
mStateChangeCallbacks 是一個 RemoteCallbackList

 case MESSAGE_REGISTER_STATE_CHANGE_CALLBACK:
 {
       IBluetoothStateChangeCallback callback = (IBluetoothStateChangeCallback) msg.obj;
       mStateChangeCallbacks.register(callback);
       break;
}

frameworks\base\services\core\java\com\android\server\BluetoothManagerService.java
bindBluetoothProfileService在IBluetoothManager.aidl文件中定義
IBluetoothProfileServiceConnection 對應一個ProfileServiceConnections

    @Override
    public boolean bindBluetoothProfileService(int bluetoothProfile,
            IBluetoothProfileServiceConnection proxy) {
        synchronized (mProfileServices) {
            ProfileServiceConnections psc = mProfileServices.get(new Integer(bluetoothProfile));
            if (psc == null) {
                if (bluetoothProfile != BluetoothProfile.HEADSET) return false;
                Intent intent = new Intent(IBluetoothHeadset.class.getName());
                psc = new ProfileServiceConnections(intent); //新建一個
                if (!psc.bindService()) return false;
                //放入鍵值映射集合
                mProfileServices.put(new Integer(bluetoothProfile), psc);
            }
        }
        //交給 BluetoothHandler 去作
        // Introducing a delay to give the client app time to prepare
        Message addProxyMsg = mHandler.obtainMessage(MESSAGE_ADD_PROXY_DELAYED);
        addProxyMsg.arg1 = bluetoothProfile;
        addProxyMsg.obj = proxy;
        mHandler.sendMessageDelayed(addProxyMsg, ADD_PROXY_DELAY_MS);
        return true;
    }

frameworks\base\services\core\java\com\android\server\BluetoothManagerService.java
往 ProfileServiceConnections中加入IBluetoothProfileServiceConnection

 case MESSAGE_ADD_PROXY_DELAYED:
                {
                    ProfileServiceConnections psc = mProfileServices.get(
                            new Integer(msg.arg1));
                    IBluetoothProfileServiceConnection proxy =
                            (IBluetoothProfileServiceConnection) msg.obj;
                    psc.addProxy(proxy);
                    break;
                }

frameworks\base\services\core\java\com\android\server\BluetoothManagerService.java
mService 是 ProfileServiceConnections 內部持有的 IBinder 遠程對象

 private void addProxy(IBluetoothProfileServiceConnection proxy) {
            mProxies.register(proxy);
            if (mService != null) {
                try{
                    proxy.onServiceConnected(mClassName, mService); //執行上述回調
                } catch (RemoteException e) {
                    Slog.e(TAG, "Unable to connect to proxy", e);
                }
            } else { //服務爲空,從新綁定自身 ProfileServiceConnections
                if (!mHandler.hasMessages(MESSAGE_BIND_PROFILE_SERVICE, this)) {
                    Message msg = mHandler.obtainMessage(MESSAGE_BIND_PROFILE_SERVICE);
                    msg.obj = this;
                    mHandler.sendMessage(msg);
                }
            }
        }

frameworks\base\services\core\java\com\android\server\BluetoothManagerService.java
從新bindService

        private boolean bindService() {
            if (mIntent != null && mService == null &&
                    //Connection conn 傳的是 this
                    doBind(mIntent, this, 0, UserHandle.CURRENT_OR_SELF)) {
                Message msg = mHandler.obtainMessage(MESSAGE_BIND_PROFILE_SERVICE);
                msg.obj = this;
                mHandler.sendMessageDelayed(msg, TIMEOUT_BIND_MS);
                return true;
            }
            return false;
        }

frameworks\base\services\core\java\com\android\server\BluetoothManagerService.java
綁定成功後,會對代理逐一執行onServiceConnected回調

 @Override
        public void onServiceConnected(ComponentName className, IBinder service) {
            // remove timeout message
            mHandler.removeMessages(MESSAGE_BIND_PROFILE_SERVICE, this);
            mService = service;
            mClassName = className;
            ......
            mInvokingProxyCallbacks = true;

            final int n = mProxies.beginBroadcast();
            try {
                for (int i = 0; i < n; i++) {
                    try {
                        mProxies.getBroadcastItem(i).onServiceConnected(className, service);
                    } catch (RemoteException e) {
                        Slog.e(TAG, "Unable to connect to proxy", e);
                    }
                }
            } finally {
                mProxies.finishBroadcast();
                mInvokingProxyCallbacks = false;
            }
        }

BluetoothManagerService主要爲frameworks\base\core\java\android\bluetooth下的各類BluetoothProfile協議子類提供服務管理,實際充當的是BluetoothAdapter的代理,BluetoothAdapter提供系統API給開發者使用,同時驅動系統藍牙應用工做。
2. 藍牙適配器

frameworks\base\core\java\android\bluetooth\BluetoothAdapter.java
mService 類型爲IBluetooth, managerService類型爲BluetoothManagerService

 BluetoothAdapter(IBluetoothManager managerService) {
        try {
            mServiceLock.writeLock().lock();
            mService = managerService.registerAdapter(mManagerCallback); //註冊
        } catch (RemoteException e) {
            Log.e(TAG, "", e);
        } finally {
            mServiceLock.writeLock().unlock();
        }
        mManagerService = managerService; //BluetoothManagerService
        mLeScanClients = new HashMap<LeScanCallback, ScanCallback>();
        mToken = new Binder(); //令牌
    }

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

private static class AdapterServiceBinder extends IBluetooth.Stub { ...... }

frameworks\base\core\java\android\bluetooth\BluetoothAdapter.java
藍牙禁用

    @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
    public boolean disable() {
        try {
            return mManagerService.disable(ActivityThread.currentPackageName(), true);
        } catch (RemoteException e) {Log.e(TAG, "", e);}
        return false;
    }

frameworks\base\services\core\java\com\android\server\BluetoothManagerService.java

 private void handleDisable() {
        try {
            mBluetoothLock.readLock().lock();
            if (mBluetooth != null) {
                if (DBG) Slog.d(TAG,"Sending off request.");
                if (!mBluetooth.disable()) {
                    Slog.e(TAG,"IBluetooth.disable() returned false");
                }
            }
        } finally {
            mBluetoothLock.readLock().unlock();
        }
    }

packages\apps\Bluetooth\src\com\android\bluetooth\btservice\AdapterService.java
調用 AdapterServiceBinder 的 disable

  public boolean disable() {
            if ((Binder.getCallingUid() != Process.SYSTEM_UID) &&
                (!Utils.checkCaller())) {
                Log.w(TAG, "disable() - Not allowed for non-active user and non system user");
                return false;
            }

            AdapterService service = getService();
            if (service == null) return false;
            return service.disable();
        }

packages\apps\Bluetooth\src\com\android\bluetooth\btservice\AdapterService.java
AdapterService的 disable

 boolean disable() {
        enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission");

        debugLog("disable() called...");
        //最終交給狀態機處理
        Message m = mAdapterStateMachine.obtainMessage(AdapterState.BLE_TURN_OFF);
        mAdapterStateMachine.sendMessage(m);
        return true;
    }

packages\apps\Bluetooth\src\com\android\bluetooth\btservice\AdapterState.java
狀態機對應的處理狀態

private class OnState extends State {
        ......
        @Override
        public boolean processMessage(Message msg) {
            AdapterProperties adapterProperties = mAdapterProperties;
            ......
            switch(msg.what) {
               case BLE_TURN_OFF:
                   notifyAdapterStateChange(BluetoothAdapter.STATE_TURNING_OFF);
                   mPendingCommandState.setTurningOff(true);
                   transitionTo(mPendingCommandState); //狀態轉換

                   // Invoke onBluetoothDisable which shall trigger a
                   // setScanMode to SCAN_MODE_NONE
                   Message m = obtainMessage(SET_SCAN_MODE_TIMEOUT);
                   sendMessageDelayed(m, PROPERTY_OP_DELAY);
                   adapterProperties.onBluetoothDisable(); //禁用
                   break;

               case USER_TURN_ON:
                   break;

               default:
                   return false;
            }
            return true;
        }
    }

在packages\apps\Bluetooth\src\com\android\bluetooth\下主要是藍牙協議,適配服務,協議服務。整個協議和服務由狀態機驅動執行。
3. 系統藍牙設置

packages\apps\Settings\src\com\android\settings\bluetooth\BluetoothSettings.java
BluetoothSettings是系統藍牙操做界面

 @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        mInitialScanStarted = false;
        mInitiateDiscoverable = true;

        final SettingsActivity activity = (SettingsActivity) getActivity();
        mSwitchBar = activity.getSwitchBar();

        mBluetoothEnabler = new BluetoothEnabler(activity, new SwitchBarController(mSwitchBar),
            mMetricsFeatureProvider, Utils.getLocalBtManager(activity),
            MetricsEvent.ACTION_BLUETOOTH_TOGGLE);
        mBluetoothEnabler.setupSwitchController();
    }

packages\apps\Settings\src\com\android\settings\bluetooth\BluetoothEnabler.java
藍牙操做控制

 @Override
    public boolean onSwitchToggled(boolean isChecked) {
        if (maybeEnforceRestrictions()) {
            return true;
        }

        // Show toast message if Bluetooth is not allowed in airplane mode
        if (isChecked &&
                !WirelessUtils.isRadioAllowed(mContext, Settings.Global.RADIO_BLUETOOTH)) {
            Toast.makeText(mContext, R.string.wifi_in_airplane_mode, Toast.LENGTH_SHORT).show();
            // Reset switch to off
            mSwitch.setChecked(false);
            return false;
        }

        mMetricsFeatureProvider.action(mContext, mMetricsEvent, isChecked);

        if (mLocalAdapter != null) {
            boolean status = mLocalAdapter.setBluetoothEnabled(isChecked); //開關藍牙
            // If we cannot toggle it ON then reset the UI assets:
            // a) The switch should be OFF but it should still be togglable (enabled = True)
            // b) The switch bar should have OFF text.
            if (isChecked && !status) {
                mSwitch.setChecked(false);
                mSwitch.setEnabled(true);
                mSwitchWidget.updateTitle(false);
                return false;
            }
        }
        mSwitchWidget.setEnabled(false);
        return true;
    }

frameworks\base\packages\SettingsLib\src\com\android\settingslib\bluetooth\LocalBluetoothAdapter.java
mAdapter 是 BluetoothAdapter

 public boolean setBluetoothEnabled(boolean enabled) {
        boolean success = enabled
                ? mAdapter.enable() //開啓
                : mAdapter.disable();
        return success;
    }

frameworks\base\services\core\java\com\android\server\BluetoothManagerService.java
調用 BluetoothManagerService 的 enable 函數,最後將操做結果返回

 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
    public boolean enable() {
        try {
            return mManagerService.enable(ActivityThread.currentPackageName());
        } catch (RemoteException e) {Log.e(TAG, "", e);}
        return false;
    }

4. 藍牙HAL

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

  static {
        classInitNative();
    }

packages\apps\Bluetooth\jni\com_android_bluetooth_btservice_AdapterService.cpp

static void classInitNative(JNIEnv* env, jclass clazz) {
  jclass jniUidTrafficClass = env->FindClass("android/bluetooth/UidTraffic");
  android_bluetooth_UidTraffic.constructor =
      env->GetMethodID(jniUidTrafficClass, "<init>", "(IJJ)V");

  .....
 
  char value[PROPERTY_VALUE_MAX];
  property_get("bluetooth.mock_stack", value, "");

  const char* id =
      (strcmp(value, "1") ? BT_STACK_MODULE_ID : BT_STACK_TEST_MODULE_ID);

  hw_module_t* module;
  int err = hw_get_module(id, (hw_module_t const**)&module);

  if (err == 0) {
    hw_device_t* abstraction;
    err = module->methods->open(module, id, &abstraction); //加載藍牙模塊
    if (err == 0) {
      bluetooth_module_t* btStack = (bluetooth_module_t*)abstraction;
      sBluetoothInterface = btStack->get_bluetooth_interface();
    } else {
      ALOGE("Error while opening Bluetooth library");
    }
  } else {
    ALOGE("No Bluetooth Library found");
  }
}

packages\apps\Bluetooth\jni\com_android_bluetooth_btservice_AdapterService.cpp
調用系統藍牙堆棧處理 system/bt 目錄下

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

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

5. 藍牙數據傳輸

frameworks\base\core\java\android\bluetooth\BluetoothAdapter.java
經過套接進行數據交換傳輸 mSocket 是 BluetoothSocket

public BluetoothServerSocket listenUsingRfcommOn(int channel, boolean mitm,
            boolean min16DigitPin)
            throws IOException {
        BluetoothServerSocket socket = new BluetoothServerSocket(
                BluetoothSocket.TYPE_RFCOMM, true, true, channel, mitm, min16DigitPin);
        int errno = socket.mSocket.bindListen();
        if (channel == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) {
            socket.setChannel(socket.mSocket.getPort());
        }
        if (errno != 0) {
            //TODO(BT): Throw the same exception error code
            // that the previous code was using.
            //socket.mSocket.throwErrnoNative(errno);
            throw new IOException("Error: " + errno);
        }
        return socket;
    }

frameworks\base\core\java\android\bluetooth\BluetoothSocket.java
經過IBluetooth 的 createSocketChannel,建立FD, 監聽Socket鏈接

 /*package*/ int bindListen() {
        int ret;
        if (mSocketState == SocketState.CLOSED) return EBADFD;
        IBluetooth bluetoothProxy = BluetoothAdapter.getDefaultAdapter().getBluetoothService(null);
        try {
            //建立Socket返回文件描述符
            mPfd = bluetoothProxy.createSocketChannel(mType, mServiceName,
                    mUuid, mPort, getSecurityFlags());
        } catch (RemoteException e) {
            Log.e(TAG, Log.getStackTraceString(new Throwable()));
            return -1;
        }

        // read out port number
        try {
            synchronized(this) {
                if(mSocketState != SocketState.INIT) return EBADFD;
                if(mPfd == null) return -1;
                FileDescriptor fd = mPfd.getFileDescriptor();
                mSocket = LocalSocket.createConnectedLocalSocket(fd);
                if (DBG) Log.d(TAG, "bindListen(), new LocalSocket.getInputStream()");
                mSocketIS = mSocket.getInputStream();
                mSocketOS = mSocket.getOutputStream();
            }
            int channel = readInt(mSocketIS);
            synchronized(this) {
                if(mSocketState == SocketState.INIT)
                    mSocketState = SocketState.LISTENING;
            }
            if (mPort <= -1) {
                mPort = channel;
            } // else ASSERT(mPort == channel)
            ret = 0;
        } catch (IOException e) {
            if (mPfd != null) {
                try {
                    mPfd.close();
                } catch (IOException e1) {
                    Log.e(TAG, "bindListen, close mPfd: " + e1);
                }
                mPfd = null;
            }
            return -1;
        }
        return ret;
    }

至此咱們粗略的查看了藍牙系統框架,能夠看到,系統定義了不一樣的藍牙協議的統一行爲,讓BluetoothAdapter做爲交互中心,提供系統和應用交互的接口,BluetoothManagerService做爲BluetoothAdapter的代理,對各類協議鏈接進行處理,Setting 目錄的blutooth模塊 藉助 framwork下的SettingLib模塊與 BluetoothAdapter進行交互,最終由系統應用Bluetooth目錄下的服務負責與藍牙底層協議和硬件交互。每一層協議均可以獨立處理本身的邏輯,還能夠自由得添加新的協議,可擴展性很高。咱們就不去逐一分析各層協議的具體實現了,能夠說藍牙的用途是極普遍且重要的,不光用於數據傳輸,藍牙耳機,心跳檢測,血脂血糖檢測,VR等。  

相關文章
相關標籤/搜索