Audio 架构图

啪啪啪,滋滋滋,通常我们会在手机里听得这些杂音,特别是在一些LLD audio的情况下,更是如此。 audio 杂音产生的原因很多。
一种简单粗暴的解决方法就是增加buffer size 和buffer 数量,可是这不是问题的root cause。
通常,我们当有杂音的时候,audio 会发生“ underruns and overruns,”而 underruns and overruns, 基本是和系统的状态相关。如果Audio 的功能正常的情况下。
而 underruns and overruns 主要由以下原因引起。
Linux CFS旨在公平地在线程间公平的共享CPU资源。这种公平性由每个线程的 nice 参数来确定 。nice值的范围是-19(分配的最低或最长时间的CPU时间)到20(分配的最短或最少的CPU时间)。通常,具有相同nice值的所有线程都将获得大约相等的CPU时间,而具有数值较低的nice值的线程应期望获得更多的CPU时间。但是,CFS仅在相对较长的观察时间内才是“公平的”。在短期观察窗口中,CFS可能会以意外方式分配CPU资源。例如,它可能会使CPU从数值低的线程转移到数值高的线程。就音频而言,这可能导致underruns and overruns 。
解决方案是避免针对高性能音频线程使用CFS。从Android 4.1开始,此类线程现在使用 SCHED_FIFO调度策略,而不是CFS实施的调度策略SCHED_NORMAL(也称为 SCHED_OTHER)。
尽管现在音频线程使用SCHED_FIFO,但它们仍然容易受到其他更高优先级SCHED_FIFO线程的影响。这些通常是内核工作线程,但也可能有一些带有policy的非音频用户线程SCHED_FIFO。SCHED_FIFO 优先级范围为1到99。音频线程以优先级2或3运行。这使优先级1可用于较低优先级的线程,而优先级4至99可用于较高优先级的线程。如果系统中高于3的优先级线程很多,那么就很容易发生杂音。
所以在整个系统中,需要尽量少用高优先级的SCHED_FIFO 线程。
优先级反转 是实时系统的经典故障模式,其中,较高优先级的任务在无限制的时间内被阻塞,等待较低优先级的任务释放诸如互斥量的资源(受共享状态保护) 。
调度等待时间是线程准备运行到完成的上下文切换完成以使线程实际在CPU上运行之间的时间。延迟越短越好,并且任何超过两毫秒的时间都会导致音频问题。在模式转换期间(例如启动或关闭CPU,在安全内核和普通内核之间切换,从全功率模式切换到低功率模式或调整CPU时钟频率和电压),很可能会发生长调度延迟。
在许多设计中,CPU 0为所有外部中断服务。因此,长时间运行的中断处理程序可能会延迟其他中断,尤其是音频直接内存访问(DMA)完成中断。设计中断处理程序以快速完成操作,并将冗长的工作延迟到线程(最好是CFS线程或SCHED_FIFO优先级为1的线程)上。
同样,长时间禁用CPU 0上的中断也具有延迟音频中断服务的相同结果。等待内核旋转锁时通常会发生较长的中断禁用时间 。查看这些自旋锁以确保它们是有界的。
一个安全内核可能与audio 线程同时运行在AP 上,而安全内核操作在内核上处于活动状态的任何时间实际上都将停止在该内核上运行的普通task。如果正在运行的audio 线程 也运行安全内核,那么极有可能参数audio 杂音。 从本质上讲,安全内核的内部行为无法从更高层了解,因此,由安全内核引起的任何性能异常都特别有害。应该避免音频线程和TZ app 同时运行。