jjzjj

Android-嵌入式蓝牙 多年蓝牙产品开发学习心路历程分享-A2DP音频流的建立、A2DP播放暂停音乐命令交互、HFP、AVRCP、RFCOMM、OPP、AVDTP

短距(connectivity)知识分享 2023-12-25 原文

序言

        当你点进来看到这段话的时候,证明你真心想学好蓝牙,哈哈哈,本来想搜索蓝牙某个协议,却成了一大段废话文,但此时,别退出去,如果你是一个牛逼的蓝牙开发者,只是想了解蓝牙某个协议或者知识点,那么直接点击进入我的主页,查看蓝牙相关文章,绝对能满足你的需要。但是,如果你是一个蓝牙新人、才开始学习蓝牙开发,那么请用几分钟看完这篇文章,一定会激励你的蓝牙学习和给你提供一个正确的学习途径,废话少说,直入正题。

       PS:本文章将持续更新,内容很长,请及时收藏。

一、自我介绍

1、工作历程

        本人从事Android 蓝牙、嵌入式蓝牙开发多年,做过手机、平板、智能手表、智能手环、TWS耳机等产品,基本市面上关于蓝牙的产品都做过。

        大学本科毕业,校招进入国内500强公司,分配是手机驱动开发部门,当时对手机开发,一脸懵逼,感觉很高大上,然后就被分配到短距组,当然有的公司叫连接组(connectivity组),一般有蓝牙、wifi、gps、NFC这四个字模块,来公司的第一周,主要是公司文化等等培训,第二周我的主管让我选自己想要做的模块,我思索很久,最后选择了蓝牙,其实现在回想过来,当时选择蓝牙开发目的可能那是我手里面有个蓝牙耳机吧,哈哈哈哈哈哈。

2、学习历程

        我本科在一个普通一本工程类大学,学的是机械设计及其制造化专业,学的课程基本都是机械设计、单片机、机械电子等课程,还好大一的时候学习过C语言,可惜当时和大家一样没学懂,哈哈,大学期间还算是个好学习,认真学习,好好吃饭,大二的时候,希望毕业后去一个机械厂里,当一名机械工程师。

        大三的时候,我学习了数字电路和模拟电路课程,感觉好神奇的东西,因为学的机械产品都是看得见,摸得着的,一个小小的cpu,里面蕴藏着这么多神奇的东西,可能和大家一样,虽然模拟电子学不懂,但是觉得很神奇。此时我改变了我的就业方向,励志要成为一名硬件工程师,大三第二学期开启了我的疯狂学习之旅,开始疯狂学习数字电路,模拟电路,还买了许多硬件类书籍,学习电路。在网上买了课程,学习画PBC板子等等。

         到了大三那个暑假,硬件学的好辛苦啊,这玩意怎么这个难,抽象,此时在网上看到了嵌入式软件开发工程师,这个就业前景好,怎么怎么滴,那好吧,搞软件吧,现在回想过来,其实当时的选择真的是根据个人爱好的,没有考虑的太多。第一次下载了哔哩哔哩APP,里面有还多关于驱动学习的课程,有进程、线程、c语言、驱动开发等等,很多课程,那个暑假我就开始了学习,给大家看看我当时买的书:

 当时买的书挺多的,有的现在都丢了,就这样,一遍跟着网上视频学习,一遍看着书学习。

        到了大四的十月份,有公司来校招了,决定去试试,但结果一塌糊涂,自己学的完全和面试官问的牛头不对马嘴,面试了两家公司,以失败告终。此时,我没有放弃,决定报培训班学习,在北京报了一家嵌入式培训班,可谓是行业第一的。学习到了大四的来年三月份,不得不说,培训班学的可谓是有条理,质量还是不错的,但是学费了是高了点,2w呢。

        接下来就是找工作了,简历上写的是驱动开发工程师,开始面试了三四家小公司,基本没有通过,不得不说,小公司对应届生确实不太友好。。。。因为需求少,资金有限,所有要求高。当然,在面试过程中,也要不断的在网上搜索题目做,尤其是C语言基础题目。四月的时候 ,突然小米公司发来邮件,让我面试,哈哈哈,突然的惊喜,都不记得什么时候投过的简历。此时已经面试过三四次了,终于等来了小米面试,第一轮是电话面试,问了些C语言基础,进程、线程等等。第二轮是视频面试,是在牛客网上的,先让我做了两道C语言编程题目,我基本通过,然后问了我几个问题,无奈这个面试官是小米穿戴部门,主要是做APP层,对驱动不太了解,一直问我上层知识,我回答的是是而非,而我给人家说驱动知识,人家也不感兴趣。结果可想而知,没有通过面试,此时已经五月份了,我失落至极。

        当然,经历过小米面试,我信心大增,打开BOSS直聘,我当时是在西安,直接就筛选一万人以上的公司,也就是当年应届生入职的某ODM公司,庆幸的是,面试官刚好问的是驱动知识,三轮面试,A+通过。面试过程就写到了这儿,如果大家有想问的,在评论区留言或者私信我,我都会一一回复的。

二、Android 蓝牙开发心路历程

1、初学Android 蓝牙

        到了第一个家公司,开始学习蓝牙,学了一个多月,突然发现和驱动没有太多联系,当然,做蓝牙的工程师,有个别名,叫协议开发工程师,哈哈哈哈,世事无常,大肠包小肠。后来以至于到现在,很少做驱动了。一直搞得是蓝牙协议。

        我们公司当时是上层和协议栈是两个团队,也是说JNI往上,由java团队负责处理问题,JNI向下,协议栈和controlller都是由C语言团队来处理的,当然我也就是从协议栈开始入手了。此时,我主要语言学习放到了C语言上,基本放弃了JAVA,此时c语言基础,像static、const、结构体、枚举、联合体、回调函数、函数指针、指针函数、指针等等概念,都要深刻的学习。

        本博主所有的文章将全面分析蓝牙知识,按照下面这个图片来展开。

①第一阶段:蓝牙基础内容学习

        此时我在网上搜索蓝牙基本概念学习,蓝牙是干嘛的,有哪些协议等等,从蓝牙的概念,到每个协议的具体概念,到framework-hal-btit-bta-btm-hci - l2cap -ll-controller,等等每一层的概念都从网上搜集到资料,进行了本地整理,当然这个阶段,学习至少得两个月,当然还要学习写Anroid架构等等知识。

下面是我工作这么多年,整理的蓝牙基础知识,需要学习的直接下载就好,不用再去网上一个一个搜索,很费事的。

Android 蓝牙基本概念,每个协议介绍,ble介绍,整理了全网所有的蓝牙基本概念,便于新人学习 - 点击下载

②第二阶段:搜索连接配对

        相信大家一开始学习蓝牙,就得从打开蓝牙,搜索周围设备,配对这个流程开始学习吧,当然,配对这个流程确实是挺复杂的,那么该如何下手学习呢?从HCI日志下手学习,HCI是host和controller交互的命令-事件流程,可以清楚的看到两者之间做了哪些事情,蓝牙新手必须从HCI学习做起来。下图就是HCI搜索、连接、配对流程图:

         哈哈哈哈,是不是感觉这个图片很棒,将蓝牙连接配对流程全部写了出来,那么接下来我就将搜索、连接、配对流程简单的描述下:

        首先打开蓝牙开关后,需要搜索周围可发现的蓝牙设备,即inquiry,一般持续扫描12.8秒,这个时间是在协议栈中设置的,可更改,搜索完成后,此时还需要继续发现这些设备的姓名,即diacovery,会将扫描到的设备信息包含地址进行上报。这是可以发起某设备的连接、即建立ACL物理和逻辑链路,建立完成后,发起配对流程,一般配对有四种方式:数值比较、passkey、justwork、oob。蓝牙耳机一般采取的是justwork模式。之后就是生成link key,用来后续数据收发进行加密了。

下面是配对的整理流程,我将core5.2中整理了出来,可以说是全网最详细得了,可以点击查看:

Android 蓝牙 连接配对流程详细分析-史上最全文档

        学习完了,配对的基本概念,接下来是否要学习源码了?NO NO NO切记,不要直接看源码,Android源码博大而精深,还是从源码流程图看起,主要是看每个阶段,都在哪层哪个函数中,调用了哪个函数,这个函数是干嘛用的,就可以了,从宏观上,学习Android 蓝牙配对流程。

更多的蓝牙搜索、配对流程图,请点击下面链接查看:

Android 蓝牙配对、协议栈使能、inquiry、discovery、hci发送数据、等等详细源码流程图 - 点击下载

当你通过我画的流程图看懂了整理源码流程,那么接下来就需要详细的看源码每个函数中具体做了哪些事情,这个就比较多了,不是一天两天就能看完的,可以查看我写的源码分析来进行学习:

Android 蓝牙连接配对流程源码分析(2)-连接配对

③第三阶段:A2DP       

        相信大家学习的第一个蓝牙协议都是A2DP吧,哈哈哈,当然头最疼的也是这个协议吧,A2DP使用场景是最多的,出问题也是最多的,如果你是做Android的,那么最重要的是学习A2DP这个啦,为什么说重要呢?因为A2DP只要给音频流提供一个通道,需要audio那边将数据流发到蓝牙侧,然后蓝牙在转发出去,所以牵扯到audio,这就麻烦了,在具体项目中,很容易和audio的同事扯皮,哈哈哈哈哈。我先把A2DP发送音频流程简单描述下:

音频流传输路径:bt侧每20ms 从audio的buf中拿pcm data,之后进行encoder,然后将encoder的数据入队,之后我们stack AVDTP 会将队列里的数据写进L2CAP的buff里,如果Controller 中NOCP(Number of complete packet)回的慢,L2CAP的buff就无法发送到peer,从而造成bt侧的queue内部overflow,进而BT侧就会清除queue中的数据,从而造成了声音不连续。

下面是我写的A2DP的文章,你可以点击看看:

Android 蓝牙 A2DP基础概念、A2DP音频流的建立及传输流程、A2DP播放暂停音乐命令交互过程分析 - 史上最全分析

学习完了A2DP的基本概念,要深入学习A2DP,先从流图图学习,一定不要从源码函数学习。

下面这张图是音频流从Audio到A2dp的路径:可以说是本人用了九牛二虎之力,从网上查询资料,到抓取手机日志,到反复查看源码总结出来的流程。

 上图只是音频流的流向,如果还要深入了解A2DP,还是需要学习A2DP初始化、使能,java-framework的实现流程,这样才能彻底理解,完整的A2DP使能、连接、播放流程图请点击下面链接查看:

Android A2dp 初始化,连接,音乐播放、avrcp连接源码流程,非常详细的从btif-bta-btm-hci 数据流程 - 点击下载

当看完流程图分析了,接下来就是学习源码了,这个其实还是蛮难的,因为每个函数都是很长的,代码量很大,要想理解每句代码的含义,还是需要有别人的指导才能进行,我分析了A2DP源码函数,将每个函数都一一进行了剖析,使Android 蓝牙开发者,更能清楚的理解:

Android 蓝牙A2dp-Avrcp初始化-连接-播放源码分析文档大全,非常详细的从btif-bta-btm-hci 数据流 - 点击下载

第三阶段:HFP

        HFP是手机蓝牙与外设连接的时候,第一个就连接上的协议,优先级是最高的,首先建立了Rfcomm通道,主要用来进行AT命令交互,然后建立SLC服务层,用来交互编码格式等等一些信息,最后是当有电话来临时候,发起eSCO链路的建立。HFP的学习过程中还要进行Telecomm的学习,应该毕竟是和打电话有关的,所以必要情况下还是要学习medom的知识。

和之前一样,先学习Android  蓝牙HFP的源码流程图,从整体上了解HFP协议:

Android 蓝牙HFP 初始化init,协议连接,andio连接,非常详细的从btif-bta-btm-hci 数据流程走 - 点击下载

接下来就是源码的学习了:

Android 蓝牙HFP 初始化init,协议连接,andio连接,非常详细的从btif-bta-btm-hci 数据流程走 - 点击下载

⑤第四阶段:AVRCP

        AVRCP协议是Device端用来控制Target端的,比如说播放音乐下一曲、上一曲、暂停、音量加减等等,当A2DP 连接成功后,会连接AVRCP协议的,具体的AVRCP概念可以看我这篇文章:

Android-蓝牙AVRCP 以及 绝对音量(absolute volume)概述-A2dp - 点击下载

        其实这个协议稍微比较简单,在实际项目开发过程,设计比较多的问题,就是绝对音量的问题,我们都知道,绝对音量就是使用的是AVRCP协议,有时候某个设备兼容性的问题,我们可能将device的绝对音量功能添加到黑名单中,来避免绝对音量的问题。可以看下我写的这篇文档,主要将如何将设备添加到黑名单中:

Android 蓝牙AVRCP 专题(2)-----黑名单

⑥第五阶段:OPP

        OPP协议在手机端是用来传输文件的,在嵌入式开发中,是没有这个协议的,很多人可能在手机上都已经忽略掉这个功能了,但对于我们蓝牙开发者来说的话,还是要关注下的,因为在手机开发中,会有一个测试项:利用opp协议传输文件,测试功耗,那么我们还是要学习写这个协议的。可以参考我这篇文档,将OPP流程进行全面的分析:

Android 蓝牙opp obex协议连接源码分析(1)-opp连接

⑦第六阶段:PBAP

        PBAP协是是都用来同步电话本的,比如我们利用车载设备来拨打电话时候,或者在开发智能手表项目时候,在device端拨打电话时候,就需要利用到这个协议了,来进行电话号码的拉取,

具体的代码流程参考我写的这篇文章:

Android 蓝牙 PBAP obex协议详解 - 史上最全

⑧第七阶段:RFCOMM

        RFCOMM协议,这个协议很重要,目前hfp 、opp、spp等等底层都是通过rfcomm来传输数据的,这个协议的重点在于:

      1、全双工:也就是master和slave都可以发起连接,并且CID号是固定的,也就是在代码中写死的。

     2、rfcomm流控:发送数据肯定要流控,不管项目中还是面试中,都会问道rfcomm流控这个问题,所有要多学习:下面这篇文件将rfcomm流控讲解的非常清楚,可以详细看看:

Android 蓝牙 SPP串口协议 rfcomm 流控以及credit配置​​​​​​

看完rfcomm基本概念后,就要学习源码了,当前本博主很贴心的给大家梳理出来了。请点击下面连接下载查看,因为是word格式,比较多。

Android 蓝牙hfp初始化、rfcomm连接、slc连接、sco连接源代码分析大全,非常详细的从btif-bta-btm

今天就先写到这里了,过几天再更新,有学习蓝牙的朋友可以评论或者私信留言哦,我都会一一回复的哦。

有关Android-嵌入式蓝牙 多年蓝牙产品开发学习心路历程分享-A2DP音频流的建立、A2DP播放暂停音乐命令交互、HFP、AVRCP、RFCOMM、OPP、AVDTP的更多相关文章

  1. LC滤波器设计学习笔记(一)滤波电路入门 - 2

    目录前言滤波电路科普主要分类实际情况单位的概念常用评价参数函数型滤波器简单分析滤波电路构成低通滤波器RC低通滤波器RL低通滤波器高通滤波器RC高通滤波器RL高通滤波器部分摘自《LC滤波器设计与制作》,侵权删。前言最近需要学习放大电路和滤波电路,但是由于只在之前做音乐频谱分析仪的时候简单了解过一点点运放,所以也是相当从零开始学习了。滤波电路科普主要分类滤波器:主要是从不同频率的成分中提取出特定频率的信号。有源滤波器:由RC元件与运算放大器组成的滤波器。可滤除某一次或多次谐波,最普通易于采用的无源滤波器结构是将电感与电容串联,可对主要次谐波(3、5、7)构成低阻抗旁路。无源滤波器:无源滤波器,又称

  2. CAN协议的学习与理解 - 2

    最近在学习CAN,记录一下,也供大家参考交流。推荐几个我觉得很好的CAN学习,本文也是在看了他们的好文之后做的笔记首先是瑞萨的CAN入门,真的通透;秀!靠这篇我竟然2天理解了CAN协议!实战STM32F4CAN!原文链接:https://blog.csdn.net/XiaoXiaoPengBo/article/details/116206252CAN详解(小白教程)原文链接:https://blog.csdn.net/xwwwj/article/details/105372234一篇易懂的CAN通讯协议指南1一篇易懂的CAN通讯协议指南1-知乎(zhihu.com)视频推荐CAN总线个人知识总

  3. 深度学习部署:Windows安装pycocotools报错解决方法 - 2

    深度学习部署:Windows安装pycocotools报错解决方法1.pycocotools库的简介2.pycocotools安装的坑3.解决办法更多Ai资讯:公主号AiCharm本系列是作者在跑一些深度学习实例时,遇到的各种各样的问题及解决办法,希望能够帮助到大家。ERROR:Commanderroredoutwithexitstatus1:'D:\Anaconda3\python.exe'-u-c'importsys,setuptools,tokenize;sys.argv[0]='"'"'C:\\Users\\46653\\AppData\\Local\\Temp\\pip-instal

  4. 神州数码无线产品(AC+AP)配置 - 2

    注意:本文主要掌握DCN自研无线产品的基本配置方法和注意事项,能够进行一般的项目实施、调试与运维AP基本配置命令AP登录用户名和密码均为:adminAP默认IP地址为:192.168.1.10AP默认情况下DHCP开启AP静态地址配置:setmanagementstatic-ip192.168.10.1AP开启/关闭DHCP功能:setmanagementdhcp-statusup/downAP设置默认网关:setstatic-ip-routegeteway192.168.10.254查看AP基本信息:getsystemgetmanagementgetmanaged-apgetrouteAP配

  5. 阿里云RDS——产品系列概述 - 2

    基础版云数据库RDS的产品系列包括基础版、高可用版、集群版、三节点企业版,本文介绍基础版实例的相关信息。RDS基础版实例也称为单机版实例,只有单个数据库节点,计算与存储分离,性价比超高。说明RDS基础版实例只有一个数据库节点,没有备节点作为热备份,因此当该节点意外宕机或者执行重启实例、变更配置、版本升级等任务时,会出现较长时间的不可用。如果业务对数据库的可用性要求较高,不建议使用基础版实例,可选择其他系列(如高可用版),部分基础版实例也支持升级为高可用版。基础版与高可用版的对比拓扑图如下所示。优势 性能由于不提供备节点,主节点不会因为实时的数据库复制而产生额外的性能开销,因此基础版的性能相对于

  6. ruby - 我正在学习编程并选择了 Ruby。我应该升级到 Ruby 1.9 吗? - 2

    我完全不是程序员,正在学习使用Ruby和Rails框架进行编程。我目前正在使用Ruby1.8.7和Rails3.0.3,但我想知道我是否应该升级到Ruby1.9,因为我真的没有任何升级的“遗留”成本。缺点是什么?我是否会遇到与普通gem的兼容性问题,或者甚至其他我不太了解甚至无法预料的问题? 最佳答案 你应该升级。不要坚持从1.8.7开始。如果您发现不支持1.9.2的gem,请避免使用它们(因为它们很可能不被维护)。如果您对gem是否兼容1.9.2有任何疑问,您可以在以下位置查看:http://www.railsplugins.or

  7. ruby - 我如何学习 ruby​​ 的正则表达式? - 2

    如何学习ruby​​的正则表达式?(对于假人) 最佳答案 http://www.rubular.com/在Ruby中使用正则表达式时是一个很棒的工具,因为它可以立即将结果可视化。 关于ruby-我如何学习ruby​​的正则表达式?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/1881231/

  8. ruby-on-rails - 2个用户之间的产品订单 - 2

    我有三个模型:User、Product、Offer以及这些模型之间的关系问题。场景:用户1发布了一个产品用户2可以向用户1发送报价,例如10美元用户1可以接受或拒绝提议我现在的问题是:用户、产品和报价之间的正确关系是什么?我如何处理那些“接受或拒绝”操作?是否有更好的解决方案?用户模型:classUser:productsend产品型号:classProduct:usersend提供模型:classOffer提前致谢:)编辑:我正在使用Rails3.2.8 最佳答案 警告:小小说来了第1部分:设置关联我建议阅读Railsguideo

  9. 深度学习12. CNN经典网络 VGG16 - 2

    深度学习12.CNN经典网络VGG16一、简介1.VGG来源2.VGG分类3.不同模型的参数数量4.3x3卷积核的好处5.关于学习率调度6.批归一化二、VGG16层分析1.层划分2.参数展开过程图解3.参数传递示例4.VGG16各层参数数量三、代码分析1.VGG16模型定义2.训练3.测试一、简介1.VGG来源VGG(VisualGeometryGroup)是一个视觉几何组在2014年提出的深度卷积神经网络架构。VGG在2014年ImageNet图像分类竞赛亚军,定位竞赛冠军;VGG网络采用连续的小卷积核(3x3)和池化层构建深度神经网络,网络深度可以达到16层或19层,其中VGG16和VGG

  10. 机器学习——时间序列ARIMA模型(四):自相关函数ACF和偏自相关函数PACF用于判断ARIMA模型中p、q参数取值 - 2

    文章目录1、自相关函数ACF2、偏自相关函数PACF3、ARIMA(p,d,q)的阶数判断4、代码实现1、引入所需依赖2、数据读取与处理3、一阶差分与绘图4、ACF5、PACF1、自相关函数ACF自相关函数反映了同一序列在不同时序的取值之间的相关性。公式:ACF(k)=ρk=Cov(yt,yt−k)Var(yt)ACF(k)=\rho_{k}=\frac{Cov(y_{t},y_{t-k})}{Var(y_{t})}ACF(k)=ρk​=Var(yt​)Cov(yt​,yt−k​)​其中分子用于求协方差矩阵,分母用于计算样本方差。求出的ACF值为[-1,1]。但对于一个平稳的AR模型,求出其滞

随机推荐