文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Android9.0 蓝牙开启流程

2022-06-06 14:01

关注

第一次接触蓝牙,先从蓝牙的开启流程入手吧,借此顺便熟悉一下蓝牙的代码架构。

1、UI

/packages/apps/Settings/src/com/android/settings/bluetooth/BluetoothSwitchPreferenceController.java

public void onClick(View v) {
    // send users to scanning settings if they click on the link in the summary text
    new SubSettingLauncher(mContext)
            .setDestination(ScanningSettings.class.getName())
            .setSourceMetricsCategory(MetricsProto.MetricsEvent.BLUETOOTH_FRAGMENT)
            .launch();
}

/packages/apps/Settings/src/com/android/settings/bluetooth/BluetoothEnabler.java

public boolean onSwitchToggled(boolean isChecked) {
    if (maybeEnforceRestrictions()) {
        triggerParentPreferenceCallback(isChecked);
        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
        mSwitchController.setChecked(false);
        triggerParentPreferenceCallback(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) {
            mSwitchController.setChecked(false);
            mSwitchController.setEnabled(true);
            mSwitchController.updateTitle(false);
            triggerParentPreferenceCallback(false);
            return false;
        }
    }
    mSwitchController.setEnabled(false);
    triggerParentPreferenceCallback(isChecked);
    return true;
}
2、framework

/frameworks/base/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothAdapter.java

public boolean 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();
    }
    return success;
}

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

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

这个方法中的关键代码是“return mManagerService.enable();” mManagerService 对象是由IBluetoothManager 接口代码实现的,IBluetoothManager实际定义的是AIDL文件,对应的类就是 BluetoothManagerService 类,在路径 frameworks/base/core/java/android/bluetooth/BluetoothManagerService 下面 。

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

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 && 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;
        mEnableExternal = true;
        // waive WRITE_SECURE_SETTINGS permission check
        sendEnableMsg(false,
                BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST, packageName);
    }
    if (DBG) {
        Slog.d(TAG, "enable returning");
    }
    return true;
}

方法中先判断是否是系统app操作蓝牙,检查是否有操作蓝牙的权限等,然后关键的代码是“sendEnableMsg(false)”,handler最后调用handleEnable方法处理该消息。

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

这里通过AIDL的方式,调用Bluetooth App 中的AdapterService 。先绑定服务,然后注册Ibluetooth回调函数,之后调用enable方法方法开启蓝牙。所以之后就从Framworks 跳到 Bluetooth APP 中继续分析。

3、Bluetooth APP

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

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 =  " + quietMode);
    mQuietmode = quietMode;
    mAdapterStateMachine.sendMessage(AdapterState.BLE_TURN_ON);
    return true;
}
private class OffState extends BaseAdapterState {
    @Override
    int getStateValue() {
        return BluetoothAdapter.STATE_OFF;
    }
    @Override
    public boolean processMessage(Message msg) {
        switch (msg.what) {
            case BLE_TURN_ON:
                transitionTo(mTurningBleOnState);
                break;
            default:
                infoLog("Unhandled message - " + messageString(msg.what));
                return false;
        }
        return true;
    }
}
private class TurningBleOnState extends BaseAdapterState {
    @Override
    int getStateValue() {
        return BluetoothAdapter.STATE_BLE_TURNING_ON;
    }
    @Override
    public void enter() {
        super.enter();
        sendMessageDelayed(BLE_START_TIMEOUT, BLE_START_TIMEOUT_DELAY);
        mAdapterService.bringUpBle();
    }
    @Override
    public void exit() {
        removeMessages(BLE_START_TIMEOUT);
        super.exit();
    }
    @Override
    public boolean processMessage(Message msg) {
        switch (msg.what) {
            case BLE_STARTED:
                transitionTo(mBleOnState);
                break;
            case BLE_START_TIMEOUT:
                errorLog(messageString(msg.what));
                transitionTo(mTurningBleOffState);
                break;
            default:
                infoLog("Unhandled message - " + messageString(msg.what));
                return false;
        }
        return true;
    }
}

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

void bringUpBle() {
    debugLog("bleOnProcessStart()");
    if (getResources().getBoolean(
            R.bool.config_bluetooth_reload_supported_profiles_when_enabled)) {
        Config.init(getApplicationContext());
    }
    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) {
        Log.w(TAG, "RemoteException trying to send a reset to BatteryStats");
    }
    StatsLog.write_non_chained(StatsLog.BLE_SCAN_STATE_CHANGED, -1, null,
            StatsLog.BLE_SCAN_STATE_CHANGED__STATE__RESET, false, false, false);
    //Start Gatt service
    setProfileServiceState(GattService.class, BluetoothAdapter.STATE_ON);
}

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

private BondStateMachine(AdapterService service, AdapterProperties prop,
        RemoteDevices remoteDevices) {
    super("BondStateMachine:");
    addState(mStableState);
    addState(mPendingCommandState);
    mRemoteDevices = remoteDevices;
    mAdapterService = service;
    mAdapterProperties = prop;
    mAdapter = BluetoothAdapter.getDefaultAdapter();
    setInitialState(mStableState);
}
private class StableState extends State {
    @Override
    public void enter() {
        infoLog("StableState(): Entering Off State");
    }
    @Override
    public boolean processMessage(Message msg) {
        BluetoothDevice dev = (BluetoothDevice) msg.obj;
        switch (msg.what) {
            case CREATE_BOND:
                OobData oobData = null;
                if (msg.getData() != null) {
                    oobData = msg.getData().getParcelable(OOBDATA);
                }
                createBond(dev, msg.arg1, oobData, true);
                break;
            case REMOVE_BOND:
                removeBond(dev, true);
                break;
            case BONDING_STATE_CHANGE:
                int newState = msg.arg1;
            
                if (newState == BluetoothDevice.BOND_BONDING) {
                    sendIntent(dev, newState, 0);
                    transitionTo(mPendingCommandState);
                } else if (newState == BluetoothDevice.BOND_NONE) {
                
                    sendIntent(dev, newState, 0);
                } else {
                    Log.e(TAG, "In stable state, received invalid newState: "
                            + state2str(newState));
                }
                break;
            case CANCEL_BOND:
            default:
                Log.e(TAG, "Received unhandled state: " + msg.what);
                return false;
        }
        return true;
    }
}

通过调用adapterService.enableNative()方法,开始调用JNI方法,进入C/C++层。adapterService.enableNative对应的cpp文件为
/packages/apps/Bluetooth/jni/com_android_bluetooth_btservice_AdapterService.cpp

static jboolean enableNative(JNIEnv* env, jobject obj, 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;
}

通过调用“int ret = sBluetoothInterface->enable()”来驱动底层打开蓝牙开关。接下来就是C里面对打开蓝牙的实现。

4、蓝牙协议栈

/system/bt/btif/src/bluetooth.cc

static int enable(bool start_restricted) {
  LOG_INFO(LOG_TAG, "%s: start restricted = %d", __func__, start_restricted);
  restricted_mode = start_restricted;
  if (!interface_ready()) return BT_STATUS_NOT_READY;
  stack_manager_get_interface()->start_up_stack_async();
  return BT_STATUS_SUCCESS;
}

enable方法会调用start_up_stack_async方法,start_up_stack_async的实现在stack_manager.c 文件中:
/system/bt/btif/src/stack_manager.cc

static void start_up_stack_async(void) {
  thread_post(management_thread, event_start_up_stack, NULL);
}

通过thread_post异步event_start_up_stack,来启动蓝牙栈

static void event_start_up_stack(UNUSED_ATTR void* context) {
  if (stack_is_running) {
    LOG_INFO(LOG_TAG, "%s stack already brought up", __func__);
    return;
  }
  ensure_stack_is_initialized();
  LOG_INFO(LOG_TAG, "%s is bringing up the stack", __func__);
  future_t* local_hack_future = future_new();
  hack_future = local_hack_future;
  // Include this for now to put btif config into a shutdown-able state
  module_start_up(get_module(BTIF_CONFIG_MODULE));
  bte_main_enable();
  if (future_await(local_hack_future) != FUTURE_SUCCESS) {
    LOG_ERROR(LOG_TAG, "%s failed to start up the stack", __func__);
    stack_is_running = true;  // So stack shutdown actually happens
    event_shut_down_stack(NULL);
    return;
  }
  stack_is_running = true;
  LOG_INFO(LOG_TAG, "%s finished", __func__);
  btif_thread_post(event_signal_stack_up, NULL);
}

bte_main_enable()方法中进行btsnoop_module和hci_module的启动以及启动BTU操作。


作者:二十岁了还没有去过星巴克


阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-移动开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯