Day4.AndroidAudio初始化

1.AudioServer初始化

AudioServer 是 Android 音频系统的核心服务,负责管理音频硬件资源、音频策略调度、跨进程音频通信等核心功能。它由 Init 进程启动,是系统核心服务之一,直接影响音频播放、录音、音效处理等功能的正常运行。

1.1AudioServer服务创建过程

Init 进程通过解析/system/bin/audioserver/audioserver.rc配置文件,完成 AudioServer 的服务定义与启动参数配置。

复制代码
service audioserver /system/bin/audioserver  
    class core  
    user audioserver  
    # media gid needed for /dev/fm (radio) and for /data/misc/media (tee)  
    group audio camera drmrpc media mediadrm net_bt net_bt_admin net_bw_acct wakelock  
    capabilities BLOCK_SUSPEND  
    # match rtprio cur / max with sensor service as we handle AR/VR HID sensor data.  
    rlimit rtprio 10 10  
    ioprio rt 4  
    task_profiles ProcessCapacityHigh HighPerformance  
    onrestart restart vendor.audio-hal  
    onrestart restart vendor.audio-hal-aidl  
    onrestart restart vendor.audio-effect-hal-aidl  
    onrestart restart vendor.audio-hal-4-0-msd  
    onrestart restart audio_proxy_service  
​  
on property:vts.native_server.on=1  
    stop audioserver  
on property:vts.native_server.on=0  
    start audioserver  
​  
on property:init.svc.audioserver=stopped  
    stop vendor.audio-hal  
    stop vendor.audio-hal-aidl  
    stop vendor.audio-effect-hal-aidl  
    stop vendor.audio-hal-4-0-msd  
    stop audio_proxy_service  
    # See b/155364397. Need to have HAL service running for VTS.  
    # Can't use 'restart' because then HAL service would restart  
    # audioserver bringing it back into running state.  
    start vendor.audio-hal  
    start vendor.audio-hal-aidl  
    start vendor.audio-effect-hal-aidl  
    start vendor.audio-hal-4-0-msd  
    start audio_proxy_service  
​  
on property:init.svc.audioserver=running && property:vts.native_server.on=1  
    # See b/378773354. To ensure the audioserver disable when  
    # running test suite, this would cover the double start  
    # request from init that caused test flaky.  
    stop audioserver  
​  
on property:init.svc.audioserver=running  
    start vendor.audio-hal  
    start vendor.audio-hal-aidl  
    start vendor.audio-effect-hal-aidl  
    start vendor.audio-hal-4-0-msd  
    start audio_proxy_service  
​  
on property:sys.audio.restart.hal=1  
    # See b/159966243. Avoid restart loop between audioserver and HAL.  
    # Keep the original service names for backward compatibility  
    stop vendor.audio-hal  
    stop vendor.audio-hal-aidl  
    stop vendor.audio-effect-hal-aidl  
    stop vendor.audio-hal-4-0-msd  
    stop audio_proxy_service  
    start vendor.audio-hal  
    start vendor.audio-hal-aidl  
    start vendor.audio-effect-hal-aidl  
    start vendor.audio-hal-4-0-msd  
    start audio_proxy_service  
    # reset the property  
    setprop sys.audio.restart.hal 0  
    on init  
    mkdir /dev/socket/audioserver 0775 audioserver audioserver
  1. 服务定义

    service audioserver /system/bin/audioserver

    class core

    user audioserver

    • 定义了 audioserver 服务的启动路径 /system/bin/audioserver

    • class core 表示该服务属于核心服务类。

    • user audioserver 指定该服务以 audioserver 用户身份运行,确保权限隔离。

  2. 权限组

    group audio camera drmrpc media mediadrm net_bt net_bt_admin net_bw_acct wakelock

    • 指定了服务所属的权限组,允许它访问音频设备、摄像头、蓝牙功能、网络带宽计费等资源。
  3. 能力与资源限制

    capabilities BLOCK_SUSPEND

    rlimit rtprio 10 10

    ioprio rt 4

    task_profiles ProcessCapacityHigh HighPerformance

    • BLOCK_SUSPEND:允许服务阻止设备进入休眠状态。

    • rlimit rtprioioprio rt:设置实时优先级和 I/O 优先级,确保服务在处理音频任务时具有较高的性能。

    • task_profiles:定义任务性能配置文件,优化服务的运行效率。

  4. 重启行为

    onrestart restart vendor.audio-hal

    onrestart restart vendor.audio-hal-aidl

    onrestart restart vendor.audio-effect-hal-aidl

    onrestart restart vendor.audio-hal-4-0-msd

    onrestart restart audio_proxy_service

    • audioserver 服务重启时,相关的音频 HAL(硬件抽象层)服务也会被重启,确保音频功能的正常运行。
  5. 属性触发器

    on property:vts.native_server.on=1

    stop audioserver

    on property:vts.native_server.on=0

    start audioserver

    • 根据系统属性 vts.native_server.on 的值,控制 audioserver 的启动或停止。这通常用于测试场景。
  6. 停止与启动逻辑

    on property:init.svc.audioserver=stopped

    stop vendor.audio-hal

    stop vendor.audio-hal-aidl

    stop vendor.audio-effect-hal-aidl

    stop vendor.audio-hal-4-0-msd

    stop audio_proxy_service

    start vendor.audio-hal

    start vendor.audio-hal-aidl

    start vendor.audio-effect-hal-aidl

    start vendor.audio-hal-4-0-msd

    start audio_proxy_service

    • audioserver 停止时,相关 HAL 服务也会停止并重新启动,确保系统的稳定性。
  7. 初始化行为

    on init

    mkdir /dev/socket/audioserver 0775 audioserver audioserver

    • 在系统初始化时,创建 /dev/socket/audioserver 目录,并设置权限和所有者。

1.2.AudioServer启动流程

  • audioserver服务通过/system/bin/audioserver可执行文件启动,核心逻辑在main_audioserver.cppmain函数中,流程如下:

    1. 内存限制与信号处理
    • limitProcessMemory:通过audio.maxmem属性或默认值(512MB)限制进程最大内存,避免音频服务过度占用资源。

    • signal(SIGPIPE, SIG_IGN):忽略管道断裂信号(避免音频流中断时进程异常退出)。

    2. 进程分叉
    • 父进程:运行media.log日志服务,监控子进程状态并输出资源使用日志。

    • 子进程:执行音频服务初始化(核心流程),并通过prctl设置父进程死亡时自毁(避免孤儿进程)。

    3. 线程池初始化
    • configureRpcThreadpool(4, false):初始化 HIDL RPC 线程池(4 个线程),用于与音频 HAL(硬件抽象层)进行跨进程通信(HAL 通常运行在独立进程)。

    • ProcessState::self()->startThreadPool():启动 Binder 线程池,处理应用层或其他服务通过 Binder IPC 发起的音频请求(如播放、录音)。

    4. 核心服务创建与注册
    • 创建服务实例

      • sp<AudioFlinger>::make():创建AudioFlinger实例(负责音频硬件管理、混音、音量控制等核心功能)。

      • sp<AudioPolicyService>::make():创建AudioPolicyService实例(负责音频策略决策,如音量策略、设备切换逻辑)。

    • 注册服务

      1. 本地注册:通过AudioSystem::setLocalAudioFlingersetLocalAudioPolicyService将实例注册到进程内(供本地调用)。

      2. 系统服务注册:通过IServiceManager::addService将实例注册到系统服务管理器(servicemanager),供跨进程调用(服务名称分别为IAudioFlingerAudioPolicyService)。

    5. AAudioService 初始化(低延迟音频)
    • 查询系统 MMAP 策略(

      AudioSystem::getMmapPolicyInfos

      若策略为AUTO\ALWAYS(允许内存映射),则初始化AAudioService

      • AAudioService是 Android O 引入的低延迟音频服务,基于 MMAP(内存映射)机制,支持实时音频流(如游戏音效、乐器应用),仅在策略允许时启动。
    6. 完成初始化并进入线程池
    • 记录初始化耗时(startupFinished),通过IPCThreadState::self()->joinThreadPool()进入 Binder 线程池,等待并处理外部音频请求。

frameworks/av/media/audioserver/main_audioserver.cpp

复制代码
 int main(int argc __unused, char **argv)  
 {  
     const auto startTime = std::chrono::steady_clock::now();  
     limitProcessMemory(  
         "audio.maxmem", /* "ro.audio.maxmem", property that defines limit */  
         (size_t)512 * (1 << 20), /* SIZE_MAX, upper limit in bytes */  
         20 /* upper limit as percentage of physical RAM */);  
 ​  
     signal(SIGPIPE, SIG_IGN);  
 ​  
 #if 1  
     const bool doLog = false;  
 #else  
     bool doLog = (bool) property_get_bool("ro.test_harness", 0);  
 #endif  
     pid_t childPid;  
     if (doLog && (childPid = fork()) != 0) {  
         strcpy(argv[0], "media.log");  
         sp<ProcessState> proc(ProcessState::self());  
         MediaLogService::instantiate();  
         ProcessState::self()->startThreadPool();  
         IPCThreadState::self()->joinThreadPool();  
         for (;;) {  
             siginfo_t info;  
             int ret = TEMP_FAILURE_RETRY(waitid(P_PID, childPid, &info,  
                                                 WEXITED | WSTOPPED | WCONTINUED));  
             if (ret < 0) {  
                 break;  
             }  
             char buffer[32];  
             const char *code;  
             struct rusage usage;  
             getrusage(RUSAGE_CHILDREN, &usage);  
             ALOG(LOG_ERROR, "media.log", "pid %d status %d code %s user %ld.%03lds sys %ld.%03lds",  
                     info.si_pid, info.si_status, code,  
                     usage.ru_utime.tv_sec, usage.ru_utime.tv_usec / 1000,  
                     usage.ru_stime.tv_sec, usage.ru_stime.tv_usec / 1000);  
             sp<IServiceManager> sm = defaultServiceManager();  
             sp<IBinder> binder = sm->getService(String16("media.log"));  
             if (binder != 0) {  
                 Vector<String16> args;  
                 binder->dump(-1, args);  
             }  
             switch (info.si_code) {  
             case CLD_EXITED:  
             case CLD_KILLED:  
             case CLD_DUMPED: {  
                 ALOG(LOG_INFO, "media.log", "exiting");  
                 _exit(0);  
                 // not reached  
                 }  
             default:  
                 break;  
             }  
         }  
     } else {  
         // all other services  
         if (doLog) {  
             prctl(PR_SET_PDEATHSIG, SIGKILL);   // if parent media.log dies before me, kill me also  
             setpgid(0, 0);                      // but if I die first, don't kill my parent  
         }  
         android::hardware::configureRpcThreadpool(4, false /*callerWillJoin*/);  
         ProcessState::self()->startThreadPool();  
         const auto af = sp<AudioFlinger>::make();  
         const auto afAdapter = sp<AudioFlingerServerAdapter>::make(af);  
         ALOGD("%s: AudioFlinger created", __func__);  
         ALOGW_IF(AudioSystem::setLocalAudioFlinger(af) != OK,  
                 "%s: AudioSystem already has an AudioFlinger instance!", __func__);  
         const auto aps = sp<AudioPolicyService>::make();  
         af->initAudioPolicyLocal(aps);  
         ALOGD("%s: AudioPolicy created", __func__);  
         ALOGW_IF(AudioSystem::setLocalAudioPolicyService(aps) != OK,  
                  "%s: AudioSystem already has an AudioPolicyService instance!", __func__);  
 ​  
         // Start initialization of internally managed audio objects such as Device Effects.  
         aps->onAudioSystemReady();  
 ​  
         // Add AudioFlinger and AudioPolicy to ServiceManager.  
         sp<IServiceManager> sm = defaultServiceManager();  
         sm->addService(String16(IAudioFlinger::DEFAULT_SERVICE_NAME), afAdapter,  
                 false /* allowIsolated */, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT);  
         sm->addService(String16(AudioPolicyService::getServiceName()), aps,  
                 false /* allowIsolated */, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT);  
         std::vector<AudioMMapPolicyInfo> policyInfos;  
         status_t status = AudioSystem::getMmapPolicyInfos(  
                 AudioMMapPolicyType::DEFAULT, &policyInfos);  
         if (status == NO_ERROR &&  
             std::any_of(policyInfos.begin(), policyInfos.end(), [](const auto& info) {  
                     return info.mmapPolicy == AudioMMapPolicy::AUTO ||  
                            info.mmapPolicy == AudioMMapPolicy::ALWAYS;  
             })) {  
             AAudioService::instantiate();  
         } else {  
             ALOGD("%s: Do not init aaudio service, status %d, policy info size %zu",  
                   __func__, status, policyInfos.size());  
         }  
         const auto endTime = std::chrono::steady_clock::now();  
         af->startupFinished();  
         using FloatMillis = std::chrono::duration<float, std::milli>;  
         const float timeTaken = std::chrono::duration_cast<FloatMillis>(  
                 endTime - startTime).count();  
         ALOGI("%s: initialization done in %.3f ms, joining thread pool", __func__, timeTaken);  
         IPCThreadState::self()->joinThreadPool();  
     }  
 }  

相关推荐
俺不理解16 分钟前
纯血鸿蒙 AudioRenderer+AudioCapturer+RingBuffer 实现麦克风采集+发声
音频·鸿蒙·录音·播放·纯血鸿蒙
~央千澈~21 分钟前
05百融云策略引擎项目交付-laravel实战完整交付定义常量分文件配置-独立建立lib类处理-成功导出pdf-优雅草卓伊凡
android·laravel·软件开发·金融策略
_一条咸鱼_34 分钟前
Android Runtime冷启动与热启动差异源码级分析(99)
android·面试·android jetpack
用户20187928316738 分钟前
Java序列化之幽灵船“Serial号”与永生契约
android·java
用户20187928316740 分钟前
“对象永生”的奇幻故事
android·java
枷锁—sha2 小时前
【BUUCTF系列】[HCTF 2018]WarmUp1
android·网络·web安全·网络安全
梦想改变生活3 小时前
《Flutter篇第二章》MasonryGridView瀑布流列表
android·flutter
杨航 AI3 小时前
PHP 5.5 Action Management with Parameters (English Version)
android·开发语言·php
柿蒂4 小时前
一次Android下载优化,CDN消耗占比从50+%到1%
android·android jetpack
Andrew_Ryan5 小时前
gradle set up
android