Android 蓝牙(一) Bluetooth Settings 开启流程详解

Bluedroid框架

Java                                                                                   
+--------------------------------+                                                                              
  +-----------------+     C++/C                                                                                 
  |       BTIF      |                                                                                           
  +-----------------+                                                                                           
  |       BTA       |                                                                                           
  +-----------------+                                                                                           
  | Bluedroid Stack |                                                                                           
  +-----------------+  user space                                                                               
+---------------------------------+                                                                             
                      kernel space

《Android 蓝牙(一) Bluetooth Settings 开启流程详解》

一.蓝牙主要涉及到的类

1. BluetoothSettings.java

蓝牙配置和连接管理界面,就是咱们常见的蓝牙界面。它管理着蓝牙界面的加载,蓝牙搜索,蓝牙连接,蓝牙重命名等管理功能

2. BluetoothEnable.java

蓝牙辅助类,用来管理蓝牙的开和关以及蓝牙状态的标题显示。如打开或关闭蓝牙的switchbar的状态和文本显示。

3. DeviceListPreferenceFragment.java

BluetoothSettings类的父类,是一个抽象类,该类包含了用于保存蓝牙设备的链表以及蓝牙。同时实现BluetoothCallback接口,实现蓝牙设备的一些回调方法。

4. BluetoothCallback.java

蓝牙设备的删除、扫描状态的改变、蓝牙状态的改变等回调抽象方法。

5. CachedBluetoothDevice.java

缓存蓝牙设备,该类代表了一个远程设备,它包含了蓝牙设备的一些属性(例如蓝牙地址,名字,信号强度等)。该类还可以进行蓝牙设备的连接、配对、断开连接等功能。位于SettingsLib

6. BluetoothDevice.java

表示远程蓝牙设备。 使用{@link BluetoothDevice}可以创建与相应设备的连接或查询有关它的信息,例如名称,地址,类和绑定状态。位于frameworks中

7. BluetoothDevicePreference.java

在设置界面显示蓝牙设备的偏好类型。点击界面上的配对、连接、断开就是在这操作的。

8. BluetoothAdapter.java

表示本地设备蓝牙适配器。 {@link BluetoothAdapter}允许您执行基本的蓝牙任务,例如启动设备发现,查询绑定(配对)设备列表,使用已知MAC地址实例化{@link BluetoothDevice},以及创建{@link BluetoothServerSocket} 监听来自其他设备的连接请求,并开始扫描蓝牙LE设备。位于frameworks中

9. BluetoothEventManager.java

BluetoothEventManager从蓝牙API接收广播和回调,并将UI线程上的事件分派到设置中显示。位于SettingsLib

10.LocalBluetoothAdapter.java

蓝牙接口适配为本地的蓝牙接口适配器,为应用提供接口,同时调用BluetoothAdapter的接口,起到应用和底层的适配作用。

11. CachedBluetoothDeviceManager.java

负责管理蓝牙的缓存(已配对的设备和搜索到的设备)主要都保存在List<CachedBluetoothDevice> mCachedDevices中。位于SettingsLib

12. LocalBluetoothProfileManager.java

提供访问有效的蓝牙协议对象LocalBluetoothProfile。位于SettingsLib

13. BluetoothManager.java

高级管理员用于获取{@link BluetoothAdapter}的实例并进行整体蓝牙管理。

14. BluetoothManagerService.java

15. AdapterState.java

状态机处理蓝牙适配器状态

二.蓝牙开启流程

1.BluetoothEnabler.java—>onSwitchToggled()

开启和关闭蓝牙的switchbar的监听状态存在与BluetoothEnable类中,当点击switchbar时,由于BluetoothEnabler implements SwitchWidgetController.OnSwitchChangeListener ,所以会调用onSwitchToggled

    @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) {
            //isChecked为true则开启蓝牙
            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;
    }

2.LocalBluetoothAdapter.java—>setBluetoothEnabled()

    public boolean setBluetoothEnabled(boolean enabled) {
        //调用到BluetoothAdapter.java-->enable()
        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();
        }
        return success;
    }

3.BluetoothAdapter.java–>enable()

    @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
    public boolean enable() {
        if (isEnabled()) {
            if (DBG) Log.d(TAG, "enable(): BT already enabled!");
            return true;
        }
        try {
            //走到service
            return mManagerService.enable(ActivityThread.currentPackageName());
        } catch (RemoteException e) {Log.e(TAG, "", e);}
        return false;
    }

4.BluetoothManagerService.java—>enable()

public boolean enable(String packageName) throws RemoteException {
        final int callingUid = Binder.getCallingUid();
        final boolean callerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID;

        if (isBluetoothDisallowed()) {
            if (DBG) {
                Slog.d(TAG,"enable(): not enabling - bluetooth disallowed");
            }
            return false;
        }

        if (!callerSystem) {
            if (!checkIfCallerIsForegroundUser()) {
                Slog.w(TAG, "enable(): not allowed for non-active and non system user");
                return false;
            }

            mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
                    "Need BLUETOOTH ADMIN permission");

            if (!isEnabled() && mPermissionReviewRequired && !CtaManagerFactory.getInstance().
                makeCtaManager().isSystemApp(mContext, packageName)
                    && startConsentUiIfNeeded(packageName, callingUid,
                            BluetoothAdapter.ACTION_REQUEST_ENABLE)) {
                return false;
            }
        }

        if (DBG) {
            Slog.d(TAG,"enable(" + packageName + "):  mBluetooth =" + mBluetooth +
                    " mBinding = " + mBinding + " mState = " +
                    BluetoothAdapter.nameForState(mState));
        }

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

4.BluetoothManagerService.java—>sendEnableMsg()
 

    private void sendEnableMsg(boolean quietMode, String packageName) {
        mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_ENABLE,
                             quietMode ? 1 : 0, 0));
        addActiveLog(packageName, true);
    }
                case MESSAGE_ENABLE:
                    if (DBG) {
                        Slog.d(TAG, "MESSAGE_ENABLE(" + msg.arg1 + "): mBluetooth = " + mBluetooth);
                    }
                    mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE);
                    mEnable = true;

                    // Use service interface to get the exact state
                    int state = 0;
                    try {
                        mBluetoothLock.readLock().lock();
                        if (mBluetooth != null) {
                            state = mBluetooth.getState();
                            if (state == BluetoothAdapter.STATE_BLE_ON) {
                                Slog.w(TAG, "BT Enable in BLE_ON State, going to ON");
                                mBluetooth.onLeServiceUp();
                                persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH);
                                break;
                            }
                        }
                    } catch (RemoteException e) {
                        Slog.e(TAG, "", e);
                    } finally {
                        mBluetoothLock.readLock().unlock();
                    }

                    mQuietEnable = (msg.arg1 == 1);
                    if (mBluetooth == null) {
                        handleEnable(mQuietEnable);
                    } else {
                        // M: ALPS03489521: Don't restart BT when BT is turning on
                        if (state == BluetoothAdapter.STATE_BLE_TURNING_ON ||
                                state == BluetoothAdapter.STATE_TURNING_ON ||
                                state == BluetoothAdapter.STATE_ON) {
                            break;
                        }
                        //
                        // We need to wait until transitioned to STATE_OFF and
                        // the previous Bluetooth process has exited. The
                        // waiting period has three components:
                        // (a) Wait until the local state is STATE_OFF. This
                        //     is accomplished by "waitForOnOff(false, true)".
                        // (b) Wait until the STATE_OFF state is updated to
                        //     all components.
                        // (c) Wait until the Bluetooth process exits, and
                        //     ActivityManager detects it.
                        // The waiting for (b) and (c) is accomplished by
                        // delaying the MESSAGE_RESTART_BLUETOOTH_SERVICE
                        // message. On slower devices, that delay needs to be
                        // on the order of (2 * SERVICE_RESTART_TIME_MS).
                        //
                        waitForOnOff(false, true);
                        Message restartMsg = mHandler.obtainMessage(
                                MESSAGE_RESTART_BLUETOOTH_SERVICE);
                        mHandler.sendMessageDelayed(restartMsg,
                                2 * SERVICE_RESTART_TIME_MS);
                    }
                    break;

5.BluetoothManagerService.java—>handleEnable()

在这里会调用到IBluetooth的客户端代理类mBluetooth = IBluetooth.Stub.asInterface(Binder.allowBlocking(service));

调用mBluetooth.enable()

    private void handleEnable(boolean quietMode) {
        mQuietEnable = quietMode;

        try {
            mBluetoothLock.writeLock().lock();
            if ((mBluetooth == null) && (!mBinding)) {
                //Start bind timeout and bind
                Message timeoutMsg=mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND);
                mHandler.sendMessageDelayed(timeoutMsg,TIMEOUT_BIND_MS);
                Intent i = new Intent(IBluetooth.class.getName());
                if (!doBind(i, mConnection,Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT,
                        UserHandle.CURRENT)) {
                    mHandler.removeMessages(MESSAGE_TIMEOUT_BIND);
                } else {
                    mBinding = true;
                }
            } else if (mBluetooth != null) {
                //Enable bluetooth
                try {
                    if (!mQuietEnable) {

                        //开启蓝牙
                        if(!mBluetooth.enable()) {
                            Slog.e(TAG,"IBluetooth.enable() returned false");
                        }
                    }
                    else {
                        if(!mBluetooth.enableNoAutoConnect()) {
                            Slog.e(TAG,"IBluetooth.enableNoAutoConnect() returned false");
                        }
                    }
                } catch (RemoteException e) {
                    Slog.e(TAG,"Unable to call enable()",e);
                }
            }
        } finally {
            mBluetoothLock.writeLock().unlock();
        }
    }

5.AdapterService.java—>AdapterServiceBinder —>enable()

AdapterService位于Bluetooth包下,其内部类AdapterServiceBinder extends IBluetooth.Stub,

        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();
        }

6.AdapterService.java—>enable()

发送AdapterState.BLE_TURN_ON信息

     public synchronized boolean enable(boolean quietMode) {
         enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission");

         // Enforce the user restriction for disallowing Bluetooth if it was set.
         if (mUserManager.hasUserRestriction(UserManager.DISALLOW_BLUETOOTH, UserHandle.SYSTEM)) {
            debugLog("enable() called when Bluetooth was disallowed");
            return false;
         }

         debugLog("enable() - Enable called with quiet mode status =  " + mQuietmode);
         mQuietmode = quietMode;
         Message m = mAdapterStateMachine.obtainMessage(AdapterState.BLE_TURN_ON);
         mAdapterStateMachine.sendMessage(m);
         mBluetoothStartTime = System.currentTimeMillis();
         return true;
     }

7.AdapterState.java—>OffState

对BLE_TURN_ON消息进行处理

               case BLE_TURN_ON:
                   notifyAdapterStateChange(BluetoothAdapter.STATE_BLE_TURNING_ON);
                   mPendingCommandState.setBleTurningOn(true);
                   transitionTo(mPendingCommandState);
                   sendMessageDelayed(BLE_START_TIMEOUT, BLE_START_TIMEOUT_DELAY);
                   adapterService.BleOnProcessStart();
                   break;

8.AdapterService.java—>BleOnProcessStart()

    void BleOnProcessStart() {
        debugLog("BleOnProcessStart()");

        if (getResources().getBoolean(
                R.bool.config_bluetooth_reload_supported_profiles_when_enabled)) {
            Config.init(getApplicationContext());
        }

        Class[] supportedProfileServices = Config.getSupportedProfiles();
        //Initialize data objects
        for (int i=0; i < supportedProfileServices.length;i++) {
            mProfileServicesState.put(supportedProfileServices[i].getName(),BluetoothAdapter.STATE_OFF);
        }

        // Reset |mRemoteDevices| whenever BLE is turned off then on
        // This is to replace the fact that |mRemoteDevices| was
        // reinitialized in previous code.
        //
        // TODO(apanicke): The reason is unclear but
        // I believe it is to clear the variable every time BLE was
        // turned off then on. The same effect can be achieved by
        // calling cleanup but this may not be necessary at all
        // We should figure out why this is needed later
        mRemoteDevices.reset();
        mAdapterProperties.init(mRemoteDevices);

        debugLog("BleOnProcessStart() - Make Bond State Machine");
        mBondStateMachine = BondStateMachine.make(this, mAdapterProperties, mRemoteDevices);

        mJniCallbacks.init(mBondStateMachine,mRemoteDevices);

        try {
            mBatteryStats.noteResetBleScan();
        } catch (RemoteException e) {
            // Ignore.
        }

        //Start Gatt service
        //在这里会启动PrfileSerice,最终调用到enableNative()
        setGattProfileServiceState(supportedProfileServices,BluetoothAdapter.STATE_ON);
    }

 

    原文作者:lz强
    原文地址: https://blog.csdn.net/liu362732346/article/details/81776675
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞