【Bluedroid】A2dp初始化流程源码分析

一、概述

Bluedroid是Android系统中用于蓝牙通信的底层协议栈,它支持多种蓝牙协议,包括A2DP(Advanced Audio Distribution Profile,高级音频分发协议)。A2DP主要用于通过蓝牙传输高质量音频,如立体声音乐。以下是Bluedroid中A2DP初始化的基本流程。

1.1. 启动BluetoothAdapter服务

  • 调用enable方法:首先,系统会调用BluetoothAdapter的enable方法以启动蓝牙服务。如果Bluedroid尚未初始化,则会先进行初始化。
  • 绑定服务:在BluetoothManagerService中,通过绑定服务的方式连接到BluetoothAdapterService和GattService等蓝牙相关服务。

1.2. 初始化BluetoothAdapterService

  • 加载蓝牙库:BluetoothAdapterService在初始化过程中会加载蓝牙相关的库文件(如libbluetooth.so),这些库文件包含了实现蓝牙协议栈所需的代码。
  • 创建接口:通过dlopen和dlsym等函数,从加载的库文件中获取蓝牙接口的指针,以便后续调用蓝牙相关的API。

1.3. 初始化A2DP Profile

  • 启动核心服务:在BluetoothAdapterService中,会启动包括A2DP在内的核心蓝牙服务。这通常是通过发送消息给服务处理线程,并调用相应的服务启动函数来实现的。
  • 初始化 A2dp 模块自身:这一步会创建和初始化 A2dp 相关的模块或对象。例如,可能会初始化一些用于管理 A2dp 连接状态、音频编解码器(codec)配置、数据传输缓冲等方面的内部数据结构和对象。
  • 设置编解码器优先级和支持情况:A2dp 支持多种音频编解码器,如 SBC(Subband Coding)、AAC(Advanced Audio Coding)等。在初始化过程中,会根据设备的硬件能力和用户设置(如果有)来确定各种编解码器的优先级顺序。通常会将设备支持较好、音质和性能综合表现较好的编解码器设置为较高优先级。同时,也会确定设备对各种编解码器的支持情况,并记录下来,以便在后续连接和音频传输过程中能够根据实际情况选择合适的编解码器。
  • 注册回调函数:为了能够在 A2dp 连接建立、音频传输过程中出现各种事件(如连接成功、连接断开、音频播放暂停等)时进行相应的处理,会注册一系列回调函数。这些回调函数通常会与上层应用(如音乐播放应用)或系统的其他相关部分进行交互,以便及时将 A2dp 相关的事件信息传递给需要的地方,并根据事件进行相应的操作。
  • 创建状态机:A2DP服务内部会创建一个状态机来管理A2DP的连接状态和数据传输。这个状态机会根据接收到的命令和事件来更新A2DP的状态,并触发相应的操作。

1.4. 建立A2DP连接

  • 搜索设备:在成功初始化A2DP Profile后,用户可以通过蓝牙设置界面搜索附近的蓝牙设备。
  • 选择设备并连接:从搜索结果中选择要连接的蓝牙设备,并发起连接请求。A2DP服务会处理这个请求,并与选定的设备进行配对和连接。
  • 建立数据传输通道:一旦连接成功,A2DP服务会建立数据传输通道,以便在设备和蓝牙音频设备之间传输音频数据。

1.5. 音频数据传输

  • 配置音频参数:在建立数据传输通道之前,A2DP服务会配置音频参数,如采样率、比特率等。这些参数会影响音频数据的质量和传输速度。
  • 开始数据传输:配置完成后,A2DP服务会开始传输音频数据。音频数据会通过之前建立的数据传输通道发送到蓝牙音频设备。

1.6. 断开A2DP连接

  • 发起断开请求:当用户不再需要蓝牙音频连接时,可以通过蓝牙设置界面发起断开请求。
  • 处理断开请求:A2DP服务会处理这个请求,并断开与蓝牙音频设备的连接。同时,它会释放与连接相关的资源,以便后续使用。

Bluedroid中A2DP的初始化流程涉及多个步骤和组件的协同工作。这些步骤包括启动BluetoothAdapter服务、初始化BluetoothAdapterService、初始化A2DP Profile、建立A2DP连接、音频数据传输以及断开A2DP连接等。通过这些步骤,Bluedroid能够支持高质量的蓝牙音频传输。

二、源码分析

从初始化蓝牙A2DP(Advanced Audio Distribution Profile)接口的本地(native)函数开始分析。initNative通过一系列严谨的步骤,包括资源清理、回调对象设置、编解码器配置准备以及接口初始化等操作,确保了蓝牙 A2DP 功能在本地环境下能够正确初始化并在初始化成功后处于可用状态,为后续的音频传输等相关操作奠定了基础。 说明:源码基于Android14分析

initNative

packages/modules/Bluetooth/android/app/jni/com_android_bluetooth_a2dp.cpp
static void initNative(JNIEnv* env, jobject object,jint maxConnectedAudioDevices,jobjectArray codecConfigArray,jobjectArray codecOffloadingArray) {std::unique_lock<std::shared_timed_mutex> interface_lock(interface_mutex);std::unique_lock<std::shared_timed_mutex> callbacks_lock(callbacks_mutex);const bt_interface_t* btInf = getBluetoothInterface();if (btInf == nullptr) {log::error("Bluetooth module is not loaded");return;}if (sBluetoothA2dpInterface != nullptr) {log::warn("Cleaning up A2DP Interface before initializing...");sBluetoothA2dpInterface->cleanup();sBluetoothA2dpInterface = nullptr;}if (mCallbacksObj != nullptr) {log::warn("Cleaning up A2DP callback object");env->DeleteGlobalRef(mCallbacksObj);mCallbacksObj = nullptr;}if ((mCallbacksObj = env->NewGlobalRef(object)) == nullptr) {log::error("Failed to allocate Global Ref for A2DP Callbacks");return;}android_bluetooth_BluetoothCodecConfig.clazz = (jclass)env->NewGlobalRef(env->FindClass("android/bluetooth/BluetoothCodecConfig"));if (android_bluetooth_BluetoothCodecConfig.clazz == nullptr) {log::error("Failed to allocate Global Ref for BluetoothCodecConfig class");return;}sBluetoothA2dpInterface =(btav_source_interface_t*)btInf->get_profile_interface(BT_PROFILE_ADVANCED_AUDIO_ID);if (sBluetoothA2dpInterface == nullptr) {log::error("Failed to get Bluetooth A2DP Interface");return;}std::vector<btav_a2dp_codec_config_t> codec_priorities =prepareCodecPreferences(env, object, codecConfigArray);std::vector<btav_a2dp_codec_config_t> codec_offloading =prepareCodecPreferences(env, object, codecOffloadingArray);bt_status_t status = sBluetoothA2dpInterface->init(&sBluetoothA2dpCallbacks, maxConnectedAudioDevices, codec_priorities,codec_offloading, &supported_codecs);if (status != BT_STATUS_SUCCESS) {log::error("Failed to initialize Bluetooth A2DP, status: {}",bt_status_text(status));sBluetoothA2dpInterface = nullptr;return;}
}

通过 bt_status_t status = sBluetoothA2dpInterface->init( &sBluetoothA2dpCallbacks, maxConnectedAudioDevices, codec_priorities, codec_offloading, &supported_codecs)调用 A2DP 接口的初始化函数,并将相关参数传入,包括回调对象指针、最大连接音频设备数量、编解码器优先级配置信息、编解码器卸载配置信息以及一个用于存储支持的编解码器信息的指针(supported_codecs

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/60870.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Mac上详细配置java开发环境和软件(更新中)

文章目录 概要JDK的配置JDK下载安装配置JDK环境变量文件 Idea的安装Mysql安装和配置Navicat Premium16.1安装安装Vscode安装和配置Maven配置本地仓库配置阿里云私服Idea集成Maven 概要 这里使用的是M3型片 14.6版本的Mac 用到的资源放在网盘 链接: https://pan.baidu.com/s/17…

[⑧5G NR]: PBCH payload生成

本篇博客记录下5G PBCH信道中payload数据的生成方式。PBCH payload一共32个比特&#xff0c;基本结构如下图&#xff1a; 根据SSB PDU中bchPayloadFlag的值有三种方式得到PBCH payload。 bchPayloadFlag 0&#xff1a;全部32比特由MAC层提供。 bchPayloadFlag 1&#xff1a;M…

预处理(1)(手绘)

大家好&#xff0c;今天给大家分享一下编译器预处理阶段&#xff0c;那么我们来看看。 上面是一些预处理阶段的知识&#xff0c;那么明天给大家讲讲宏吧。 今天分享就到这里&#xff0c;谢谢大家&#xff01;&#xff01;

EEG+EMG学习系列 (2) :实时 EEG-EMG 人机界面的下肢外骨骼控制系统

[TOC]( EEGEMG学习系列(2):实时 EEG-EMG 人机界面的下肢外骨骼控制系统) 论文地址&#xff1a;https://ieeexplore.ieee.org/abstract/document/9084126 论文题目&#xff1a;Real-Time EEG–EMG Human–Machine Interface-Based Control System for a Lower-Limb Exoskeleton …

用指针遍历数组

#include<stdio.h> int main() {//定义一个二维数组int arr[3][4] {{1,2,3,4},{2,3,4,5},{3,4,5,6},};//获取二维数组的指针int (*p)[4] arr;//二维数组里存的是一维数组int[4]for (int i 0; i < 3; i){//遍历一维数组for (int j 0; j <4; j){printf("%d &…

动态规划子数组系列(二) 环形子数组的最大和

题目&#xff1a; 解析&#xff1a; 代码&#xff1a; public int maxSubarraySumCircular(int[] nums) {int sum 0;int n nums.length;int[] f new int[n1];int[] g new int[n1];int ret 0, fmax -0x3f3f3f3f, gmin Integer.MAX_VALUE;for(int i 1; i < n; i)…

element ui 搜索框中搜索关键字标红展示

示例如图 el-select上绑定remote-method属性 <el-select v-model"checkForm.type" filterable remote reserve-keyword :remote-method"remoteMethod" :loading"loading"><el-option v-for"item in options" :key"ite…

LeetCode654.最大二叉树

LeetCode刷题记录 文章目录 &#x1f4dc;题目描述&#x1f4a1;解题思路⌨C代码 &#x1f4dc;题目描述 给定一个不重复的整数数组 nums 。 最大二叉树 可以用下面的算法从 nums 递归地构建: 创建一个根节点&#xff0c;其值为 nums 中的最大值。 递归地在最大值 左边 的 子…

Charles抓https包-配置系统证书(雷电)

1、导出证书 2、下载 主页上传资源中有安装包&#xff0c;免费的 openssl 安装教程自己搜 openssl x509 -subject_hash_old -in charles.pem 3、修改证书名、后缀改成点0 雷电打开root和磁盘写入 4、导入雷电证书根目录 证书拖进去&#xff0c;基本就完成了&#xff…

Java基础——多线程

1. 线程 是一个程序内部的一条执行流程程序中如果只有一条执行流程&#xff0c;那这个程序就是单线程的程序 2. 多线程 指从软硬件上实现的多条执行流程的技术&#xff08;多条线程由CPU负责调度执行&#xff09; 2.1. 如何创建多条线程 Java通过java.lang.Thread类的对象…

【React】状态管理之Zustand

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 状态管理之Zustand引言1. Zustand 的核心特点1.1 简单直观的 API1.2 无需 Provi…

虎扑APP数据采集:JavaScript与AJAX的结合使用

引言 虎扑APP的数据采集涉及到前端和后端的交互&#xff0c;其中AJAX&#xff08;Asynchronous JavaScript and XML&#xff09;技术允许在不重新加载整个页面的情况下&#xff0c;与服务器进行数据交换和更新部分网页内容。这种技术使得数据采集过程更加高效和用户友好。然而…

高级数据结构——hash表与布隆过滤器

文章目录 hash表与布隆过滤器1. hash函数2. 选择hash函数3. 散列冲突3.1 负载因子3.2 冲突解决3. STL中的散列表 4. 布隆过滤器4.1 背景1. 应用场景2. 常见的处理场景&#xff1a; 4.2 布隆过滤器构成4.3 原理4.4 应用分析4.5 要点 5. 分布式一致性hash5.1 缓存失效问题 6. 大数…

测试实项中的偶必现难测bug--互斥逻辑异常

问题: 今天线上出了一个很奇怪的问题,看现象和接口是因为数据问题导致app模块奔溃 初步排查数据恢复后还是出现了数据重复的问题,查看后台实际只有一条数据,但是显示在app却出现了两条一模一样的置顶数据 排查: 1、顺着这个逻辑,我们准备在预发复现这个场景,先是cop…

基于Java Web 的家乡特色菜推荐系统

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

【代码大模型】Is Your Code Generated by ChatGPT Really Correct?论文阅读

Is Your Code Generated by ChatGPT Really Correct? Rigorous Evaluation of Large Language Models for Code Generation key word: evaluation framework, LLM-synthesized code, benchmark 论文&#xff1a;https://arxiv.org/pdf/2305.01210.pdf 代码&#xff1a;https:…

SpringBoot集成Dynamo(2)demo

一、dynamo local 1、建表 aws dynamodb create-table --table-name t_user --attribute-definitions AttributeNameuser_account,AttributeTypeS AttributeNameuser_name,AttributeTypeS --key-schema AttributeNameuser_account,KeyTypeHASH AttributeNameuser_name,KeyType…

Godot的开发框架应当是什么样子的?

目录 前言 全局协程还是实例协程&#xff1f; 存档&#xff01; 全局管理类&#xff1f; UI框架&#xff1f; Godot中的异步&#xff08;多线程&#xff09;加载 Godot中的ScriptableObject 游戏流程思考 结语 前言 这是一篇杂谈&#xff0c;主要内容是对我…

Spring Boot框架:电商系统的设计与实现

摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本网上商城系统就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短时间内处理完毕庞大的数据信息&…

tensorflow案例6--基于VGG16的猫狗识别(准确率99.8%+),以及tqdm、train_on_batch的简介

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 前言 本次还是学习API和如何搭建神经网络为主&#xff0c;这一次用VGG16去对猫狗分类&#xff0c;效果还是很好的&#xff0c;达到了99.8% 文章目录 1、tqdm…