当前位置:   article > 正文

Android音频框架之一 详解audioPolicy流程及HAL驱动加载与配置_安卓音频开发和音频驱动

安卓音频开发和音频驱动

一、 AndroidRuntime.so 引发思考

android 系统 framework 代码起点, frameworks/base/core/jni/AndroidRuntime.cpp 文件,
此文件是android系统主线程代码,代码内容涉及系统很多模块,此程序主要是注册模块的JNI接口方法。其中涉及到模块 native、sensorHal、media、audioflinger、displayflinger、camera、serialport、binder等,
从各模块名称上可看出是 android 系统核心组件内容,由此可见 AndroidRuntime 是系统框架的入口。
启动注册 audioRecord、audioSystem、audioTrack 模块,此模块注册是在 mediaService 模块启动之前。

defaultServiceManager 定义在 frameworks\native\libs\binder\IServiceManager.cpp

  1. sp<IServiceManager> defaultServiceManager()
  2. {
  3. std::call_once(gSmOnce, []() {
  4. sp<AidlServiceManager> sm = nullptr;
  5. while (sm == nullptr) {
  6. sm = interface_cast<AidlServiceManager>(ProcessState::self()->getContextObject(nullptr));
  7. if (sm == nullptr) {
  8. ALOGE("Waiting 1s on context object on %s.", ProcessState::self()->getDriverName().c_str());
  9. sleep(1);
  10. }
  11. }
  12. gDefaultServiceManager = sp<ServiceManagerShim>::make(sm);
  13. });
  14. return gDefaultServiceManager;
  15. }
sp<IServiceManager> sm(defaultServiceManager());

安卓源码中大量使用 sm 对象来管理系统的各种服务,添加、释放服务。用户 app 通过反射的方式获取系统的各种服务,
由此可以对安卓系统服务概念理解会更加深刻。

Binder学习之获取ServiceManager对象_sp<iservicemanager> sm = defaultservicemanager();-CSDN博客

二、 Android 音频框架

Android音频系统有两大服务:一是AudioFlinger,二是AudioPolicyService。 AudioFlinger负责向下 访问AudioHardwareInterface,
实现音频PCM数据的混音/输入/输出,实现音量调节;
AudioPolicyService负责音 频输入输出设备的连接状态,音频策略调度即音频设备(如本地CODEC、Bluetooth A2DP、Headset)的切换
策略(注意它只是负责策略,真正的切换操作是在AudioFlinger中的openOutput,毕竟 AudioFlinger负责操作底层音频硬件)。

2.0> mediaserver 和 audioserver 本地服务

在 android 系统初始化 frameworks\av\media\mediaserver\mediaserver.rc 中,启动 mediaserver 服务, 线程名称: /system/bin/mediaserver ,启动多媒体服务。

  1. on property:init.svc.media=*
  2. setprop init.svc.mediadrm ${init.svc.media}
  3. service media /system/bin/mediaserver
  4. class main
  5. user media
  6. group audio camera inet net_bt net_bt_admin net_bw_acct drmrpc mediadrm
  7. ioprio rt 4
  8. task_profiles ProcessCapacityHigh HighPerformance

frameworks/av/media/mediaserver/main_mediaserver.cpp 是入口函数, 

  1. int main(int argc __unused, char **argv __unused)
  2. {
  3. signal(SIGPIPE, SIG_IGN);
  4. sp<ProcessState> proc(ProcessState::self());
  5. sp<IServiceManager> sm(defaultServiceManager());
  6. ALOGI("ServiceManager: %p", sm.get());
  7. MediaPlayerService::instantiate();
  8. ResourceManagerService::instantiate();
  9. registerExtensions();
  10. ::android::hardware::configureRpcThreadpool(16, false);
  11. ProcessState::self()->startThreadPool();
  12. IPCThreadState::self()->joinThreadPool();
  13. ::android::hardware::joinRpcThreadpool();
  14. }

 

system/core/rootdir/init.zygote32.rc 中启动 audioserver 服务,内容如下:

  1. service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
  2. class main
  3. socket zygote stream 660 root system
  4. onrestart write /sys/android_power/request_state wake
  5. onrestart write /sys/power/state on
  6. onrestart restart audioserver ## 启动 audioserver 服务
  7. onrestart restart cameraserver ## 启动 cameraserver 服务
  8. onrestart restart media
  9. onrestart restart netd
  10. writepid /dev/cpuset/foreground/tasks

frameworks/av/media/audioserver/main_audioserver.cpp 此程序是入口函数 

  1. int main(int argc __unused, char **argv)
  2. {
  3. // TODO: update with refined parameters
  4. limitProcessMemory(
  5. "audio.maxmem", /* "ro.audio.maxmem", property that defines limit */
  6. (size_t)512 * (1 << 20), /* SIZE_MAX, upper limit in bytes */
  7. 20 /* upper limit as percentage of physical RAM */);
  8. signal(SIGPIPE, SIG_IGN);
  9. #if 1
  10. // FIXME See bug 165702394 and bug 168511485
  11. const bool doLog = false;
  12. #else
  13. bool doLog = (bool) property_get_bool("ro.test_harness", 0);
  14. #endif
  15. pid_t childPid;
  16. // FIXME The advantage of making the process containing media.log service the parent process of
  17. // the process that contains the other audio services, is that it allows us to collect more
  18. // detailed information such as signal numbers, stop and continue, resource usage, etc.
  19. // But it is also more complex. Consider replacing this by independent processes, and using
  20. // binder on death notification instead.
  21. if (doLog && (childPid = fork()) != 0) {
  22. // media.log service
  23. //prctl(PR_SET_NAME, (unsigned long) "media.log", 0, 0, 0);
  24. // unfortunately ps ignores PR_SET_NAME for the main thread, so use this ugly hack
  25. strcpy(argv[0], "media.log");
  26. sp<ProcessState> proc(ProcessState::self());
  27. MediaLogService::instantiate();
  28. ProcessState::self()->startThreadPool();
  29. IPCThreadState::self()->joinThreadPool();
  30. for (;;) {
  31. siginfo_t info;
  32. int ret = waitid(P_PID, childPid, &info, WEXITED | WSTOPPED | WCONTINUED);
  33. if (ret == EINTR) {
  34. continue;
  35. }
  36. if (ret < 0) {
  37. break;
  38. }
  39. char buffer[32];
  40. const char *code;
  41. switch (info.si_code) {
  42. case CLD_EXITED:
  43. code = "CLD_EXITED";
  44. break;
  45. case CLD_KILLED:
  46. code = "CLD_KILLED";
  47. break;
  48. case CLD_DUMPED:
  49. code = "CLD_DUMPED";
  50. break;
  51. case CLD_STOPPED:
  52. code = "CLD_STOPPED";
  53. break;
  54. case CLD_TRAPPED:
  55. code = "CLD_TRAPPED";
  56. break;
  57. case CLD_CONTINUED:
  58. code = "CLD_CONTINUED";
  59. break;
  60. default:
  61. snprintf(buffer, sizeof(buffer), "unknown (%d)", info.si_code);
  62. code = buffer;
  63. break;
  64. }
  65. struct rusage usage;
  66. getrusage(RUSAGE_CHILDREN, &usage);
  67. ALOG(LOG_ERROR, "media.log", "pid %d status %d code %s user %ld.%03lds sys %ld.%03lds",
  68. info.si_pid, info.si_status, code,
  69. usage.ru_utime.tv_sec, usage.ru_utime.tv_usec / 1000,
  70. usage.ru_stime.tv_sec, usage.ru_stime.tv_usec / 1000);
  71. sp<IServiceManager> sm = defaultServiceManager();
  72. sp<IBinder> binder = sm->getService(String16("media.log"));
  73. if (binder != 0) {
  74. Vector<String16> args;
  75. binder->dump(-1, args);
  76. }
  77. switch (info.si_code) {
  78. case CLD_EXITED:
  79. case CLD_KILLED:
  80. case CLD_DUMPED: {
  81. ALOG(LOG_INFO, "media.log", "exiting");
  82. _exit(0);
  83. // not reached
  84. }
  85. default:
  86. break;
  87. }
  88. }
  89. } else {
  90. // all other services
  91. if (doLog) {
  92. prctl(PR_SET_PDEATHSIG, SIGKILL); // if parent media.log dies before me, kill me also
  93. setpgid(0, 0); // but if I die first, don't kill my parent
  94. }
  95. android::hardware::configureRpcThreadpool(4, false /*callerWillJoin*/);
  96. sp<ProcessState> proc(ProcessState::self());
  97. sp<IServiceManager> sm = defaultServiceManager();
  98. ALOGI("ServiceManager: %p", sm.get());
  99. AudioFlinger::instantiate();
  100. AudioPolicyService::instantiate();
  101. // AAudioService should only be used in OC-MR1 and later.
  102. // And only enable the AAudioService if the system MMAP policy explicitly allows it.
  103. // This prevents a client from misusing AAudioService when it is not supported.
  104. aaudio_policy_t mmapPolicy = property_get_int32(AAUDIO_PROP_MMAP_POLICY,
  105. AAUDIO_POLICY_NEVER);
  106. if (mmapPolicy == AAUDIO_POLICY_AUTO || mmapPolicy == AAUDIO_POLICY_ALWAYS) {
  107. AAudioService::instantiate();
  108. }
  109. ProcessState::self()->startThreadPool();
  110. IPCThreadState::self()->joinThreadPool();
  111. }
  112. }

此线程启动服务有:AudioFlinger、AudioPolicyService、RadioService、SoundTriggerHwService 服务;其中 RadioService 是电话服务,不是本次讨论内容略过。

2.1> audioflinger 本地混音管理框架

AudioFlinger(下面简称AF)是整个音频系统的核心与难点。作为 Android 系统中的音频中枢,它同时也是一个系统服务,启到承上(为上层提供访问接口)启下(通过HAL来管理音频设备)的作用。 AudioFlinger 向下访问 AudioHardware,实现输出音频数据,控制音频参数。
首先看 AudioFlinger 的继承关系及父类内容,在 audioserver 函数中调用 AudioFlinger::instantiate() 函数.

  1. void AudioFlinger::instantiate() {
  2. sp<IServiceManager> sm(defaultServiceManager());
  3. sm->addService(String16(IAudioFlinger::DEFAULT_SERVICE_NAME),
  4. new AudioFlingerServerAdapter(new AudioFlinger()), false,
  5. IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT);
  6. }

在 系统服务中添加 audioService 服务内容,供用户通过服务的方式使用音频设备

AudioFlinger 构造函数内容如下:

  1. AudioFlinger::AudioFlinger()
  2. : mMediaLogNotifier(new AudioFlinger::MediaLogNotifier()),
  3. mPrimaryHardwareDev(NULL),
  4. mAudioHwDevs(NULL),
  5. mHardwareStatus(AUDIO_HW_IDLE),
  6. mMasterVolume(1.0f),
  7. mMasterMute(false),
  8. // mNextUniqueId(AUDIO_UNIQUE_ID_USE_MAX),
  9. mMode(AUDIO_MODE_INVALID),
  10. mBtNrecIsOff(false),
  11. mIsLowRamDevice(true),
  12. mIsDeviceTypeKnown(false),
  13. mTotalMemory(0),
  14. mClientSharedHeapSize(kMinimumClientSharedHeapSizeBytes),
  15. mGlobalEffectEnableTime(0),
  16. mPatchPanel(this),
  17. mDeviceEffectManager(this),
  18. mSystemReady(false)
  19. {
  20. // Move the audio session unique ID generator start base as time passes to limit risk of
  21. // generating the same ID again after an audioserver restart.
  22. // This is important because clients will reuse previously allocated audio session IDs
  23. // when reconnecting after an audioserver restart and newly allocated IDs may conflict with
  24. // active clients.
  25. // Moving the base by 1 for each elapsed second is a good compromise between avoiding overlap
  26. // between allocation ranges and not reaching wrap around too soon.
  27. timespec ts{};
  28. clock_gettime(CLOCK_MONOTONIC, &ts);
  29. // zero ID has a special meaning, so start allocation at least at AUDIO_UNIQUE_ID_USE_MAX
  30. uint32_t movingBase = (uint32_t)std::max((long)1, ts.tv_sec);
  31. // unsigned instead of audio_unique_id_use_t, because ++ operator is unavailable for enum
  32. for (unsigned use = AUDIO_UNIQUE_ID_USE_UNSPECIFIED; use < AUDIO_UNIQUE_ID_USE_MAX; use++) {
  33. mNextUniqueIds[use] =
  34. ((use == AUDIO_UNIQUE_ID_USE_SESSION || use == AUDIO_UNIQUE_ID_USE_CLIENT) ?
  35. movingBase : 1) * AUDIO_UNIQUE_ID_USE_MAX;
  36. }
  37. #if 1
  38. // FIXME See bug 165702394 and bug 168511485
  39. const bool doLog = false;
  40. #else
  41. const bool doLog = property_get_bool("ro.test_harness", false);
  42. #endif
  43. if (doLog) {
  44. mLogMemoryDealer = new MemoryDealer(kLogMemorySize, "LogWriters",
  45. MemoryHeapBase::READ_ONLY);
  46. (void) pthread_once(&sMediaLogOnce, sMediaLogInit);
  47. }
  48. // reset battery stats.
  49. // if the audio service has crashed, battery stats could be left
  50. // in bad state, reset the state upon service start.
  51. BatteryNotifier::getInstance().noteResetAudio();
  52. mDevicesFactoryHal = DevicesFactoryHalInterface::create();
  53. mEffectsFactoryHal = EffectsFactoryHalInterface::create();
  54. mMediaLogNotifier->run("MediaLogNotifier");
  55. std::vector<pid_t> halPids;
  56. mDevicesFactoryHal->getHalPids(&halPids);
  57. TimeCheck::setAudioHalPids(halPids);
  58. // Notify that we have started (also called when audioserver service restarts)
  59. mediametrics::LogItem(mMetricsId)
  60. .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_CTOR)
  61. .record();
  62. }

 C++ 中智能指针创建对象时,第一次创建会调用onFirstRef()函数,在本例中将调用 AudioFlinger::onFirstRef() 函数,
内容如下:frameworks/av/services/audioflinger/audioFlinger.cpp

  1. void AudioFlinger::onFirstRef()
  2. {
  3. Mutex::Autolock _l(mLock);
  4. /* TODO: move all this work into an Init() function */
  5. char val_str[PROPERTY_VALUE_MAX] = { 0 };
  6. if (property_get("ro.audio.flinger_standbytime_ms", val_str, NULL) >= 0) {
  7. uint32_t int_val;
  8. if (1 == sscanf(val_str, "%u", &int_val)) {
  9. mStandbyTimeInNsecs = milliseconds(int_val);
  10. ALOGI("Using %u mSec as standby time.", int_val);
  11. } else {
  12. mStandbyTimeInNsecs = kDefaultStandbyTimeInNsecs;
  13. ALOGI("Using default %u mSec as standby time.",
  14. (uint32_t)(mStandbyTimeInNsecs / 1000000));
  15. }
  16. }
  17. mMode = AUDIO_MODE_NORMAL;
  18. gAudioFlinger = this; // we are already refcounted, store into atomic pointer.
  19. mDevicesFactoryHalCallback = new DevicesFactoryHalCallbackImpl;
  20. mDevicesFactoryHal->setCallbackOnce(mDevicesFactoryHalCallback);
  21. }

 至此 audioFlinger 对象构建完成

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小丑西瓜9/article/detail/319062
推荐阅读
相关标签
  

闽ICP备14008679号