赞
踩
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
- sp<IServiceManager> defaultServiceManager()
- {
- std::call_once(gSmOnce, []() {
- sp<AidlServiceManager> sm = nullptr;
- while (sm == nullptr) {
- sm = interface_cast<AidlServiceManager>(ProcessState::self()->getContextObject(nullptr));
- if (sm == nullptr) {
- ALOGE("Waiting 1s on context object on %s.", ProcessState::self()->getDriverName().c_str());
- sleep(1);
- }
- }
-
- gDefaultServiceManager = sp<ServiceManagerShim>::make(sm);
- });
-
- return gDefaultServiceManager;
- }
sp<IServiceManager> sm(defaultServiceManager());
安卓源码中大量使用 sm 对象来管理系统的各种服务,添加、释放服务。用户 app 通过反射的方式获取系统的各种服务,
由此可以对安卓系统服务概念理解会更加深刻。
Binder学习之获取ServiceManager对象_sp<iservicemanager> sm = defaultservicemanager();-CSDN博客
Android音频系统有两大服务:一是AudioFlinger,二是AudioPolicyService。 AudioFlinger负责向下 访问AudioHardwareInterface,
实现音频PCM数据的混音/输入/输出,实现音量调节;
AudioPolicyService负责音 频输入输出设备的连接状态,音频策略调度即音频设备(如本地CODEC、Bluetooth A2DP、Headset)的切换
策略(注意它只是负责策略,真正的切换操作是在AudioFlinger中的openOutput,毕竟 AudioFlinger负责操作底层音频硬件)。
在 android 系统初始化 frameworks\av\media\mediaserver\mediaserver.rc 中,启动 mediaserver 服务, 线程名称: /system/bin/mediaserver ,启动多媒体服务。
- on property:init.svc.media=*
- setprop init.svc.mediadrm ${init.svc.media}
-
- service media /system/bin/mediaserver
- class main
- user media
- group audio camera inet net_bt net_bt_admin net_bw_acct drmrpc mediadrm
- ioprio rt 4
- task_profiles ProcessCapacityHigh HighPerformance
frameworks/av/media/mediaserver/main_mediaserver.cpp 是入口函数,
- int main(int argc __unused, char **argv __unused)
- {
- signal(SIGPIPE, SIG_IGN);
-
- sp<ProcessState> proc(ProcessState::self());
- sp<IServiceManager> sm(defaultServiceManager());
- ALOGI("ServiceManager: %p", sm.get());
- MediaPlayerService::instantiate();
- ResourceManagerService::instantiate();
- registerExtensions();
- ::android::hardware::configureRpcThreadpool(16, false);
- ProcessState::self()->startThreadPool();
- IPCThreadState::self()->joinThreadPool();
- ::android::hardware::joinRpcThreadpool();
- }
system/core/rootdir/init.zygote32.rc 中启动 audioserver 服务,内容如下:
- service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
- class main
- socket zygote stream 660 root system
- onrestart write /sys/android_power/request_state wake
- onrestart write /sys/power/state on
- onrestart restart audioserver ## 启动 audioserver 服务
- onrestart restart cameraserver ## 启动 cameraserver 服务
- onrestart restart media
- onrestart restart netd
- writepid /dev/cpuset/foreground/tasks
frameworks/av/media/audioserver/main_audioserver.cpp 此程序是入口函数
- int main(int argc __unused, char **argv)
- {
- // TODO: update with refined parameters
- 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
- // FIXME See bug 165702394 and bug 168511485
- const bool doLog = false;
- #else
- bool doLog = (bool) property_get_bool("ro.test_harness", 0);
- #endif
-
- pid_t childPid;
- // FIXME The advantage of making the process containing media.log service the parent process of
- // the process that contains the other audio services, is that it allows us to collect more
- // detailed information such as signal numbers, stop and continue, resource usage, etc.
- // But it is also more complex. Consider replacing this by independent processes, and using
- // binder on death notification instead.
- if (doLog && (childPid = fork()) != 0) {
- // media.log service
- //prctl(PR_SET_NAME, (unsigned long) "media.log", 0, 0, 0);
- // unfortunately ps ignores PR_SET_NAME for the main thread, so use this ugly hack
- strcpy(argv[0], "media.log");
- sp<ProcessState> proc(ProcessState::self());
- MediaLogService::instantiate();
- ProcessState::self()->startThreadPool();
- IPCThreadState::self()->joinThreadPool();
- for (;;) {
- siginfo_t info;
- int ret = waitid(P_PID, childPid, &info, WEXITED | WSTOPPED | WCONTINUED);
- if (ret == EINTR) {
- continue;
- }
- if (ret < 0) {
- break;
- }
- char buffer[32];
- const char *code;
- switch (info.si_code) {
- case CLD_EXITED:
- code = "CLD_EXITED";
- break;
- case CLD_KILLED:
- code = "CLD_KILLED";
- break;
- case CLD_DUMPED:
- code = "CLD_DUMPED";
- break;
- case CLD_STOPPED:
- code = "CLD_STOPPED";
- break;
- case CLD_TRAPPED:
- code = "CLD_TRAPPED";
- break;
- case CLD_CONTINUED:
- code = "CLD_CONTINUED";
- break;
- default:
- snprintf(buffer, sizeof(buffer), "unknown (%d)", info.si_code);
- code = buffer;
- break;
- }
- 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*/);
- sp<ProcessState> proc(ProcessState::self());
- sp<IServiceManager> sm = defaultServiceManager();
- ALOGI("ServiceManager: %p", sm.get());
- AudioFlinger::instantiate();
- AudioPolicyService::instantiate();
- // AAudioService should only be used in OC-MR1 and later.
- // And only enable the AAudioService if the system MMAP policy explicitly allows it.
- // This prevents a client from misusing AAudioService when it is not supported.
- aaudio_policy_t mmapPolicy = property_get_int32(AAUDIO_PROP_MMAP_POLICY,
- AAUDIO_POLICY_NEVER);
- if (mmapPolicy == AAUDIO_POLICY_AUTO || mmapPolicy == AAUDIO_POLICY_ALWAYS) {
- AAudioService::instantiate();
- }
- ProcessState::self()->startThreadPool();
- IPCThreadState::self()->joinThreadPool();
- }
- }
此线程启动服务有:AudioFlinger、AudioPolicyService、RadioService、SoundTriggerHwService 服务;其中 RadioService 是电话服务,不是本次讨论内容略过。
AudioFlinger(下面简称AF)是整个音频系统的核心与难点。作为 Android 系统中的音频中枢,它同时也是一个系统服务,启到承上(为上层提供访问接口)启下(通过HAL来管理音频设备)的作用。 AudioFlinger 向下访问 AudioHardware,实现输出音频数据,控制音频参数。
首先看 AudioFlinger 的继承关系及父类内容,在 audioserver 函数中调用 AudioFlinger::instantiate() 函数.
- void AudioFlinger::instantiate() {
- sp<IServiceManager> sm(defaultServiceManager());
- sm->addService(String16(IAudioFlinger::DEFAULT_SERVICE_NAME),
- new AudioFlingerServerAdapter(new AudioFlinger()), false,
- IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT);
- }
在 系统服务中添加 audioService 服务内容,供用户通过服务的方式使用音频设备
AudioFlinger 构造函数内容如下:
- AudioFlinger::AudioFlinger()
- : mMediaLogNotifier(new AudioFlinger::MediaLogNotifier()),
- mPrimaryHardwareDev(NULL),
- mAudioHwDevs(NULL),
- mHardwareStatus(AUDIO_HW_IDLE),
- mMasterVolume(1.0f),
- mMasterMute(false),
- // mNextUniqueId(AUDIO_UNIQUE_ID_USE_MAX),
- mMode(AUDIO_MODE_INVALID),
- mBtNrecIsOff(false),
- mIsLowRamDevice(true),
- mIsDeviceTypeKnown(false),
- mTotalMemory(0),
- mClientSharedHeapSize(kMinimumClientSharedHeapSizeBytes),
- mGlobalEffectEnableTime(0),
- mPatchPanel(this),
- mDeviceEffectManager(this),
- mSystemReady(false)
- {
- // Move the audio session unique ID generator start base as time passes to limit risk of
- // generating the same ID again after an audioserver restart.
- // This is important because clients will reuse previously allocated audio session IDs
- // when reconnecting after an audioserver restart and newly allocated IDs may conflict with
- // active clients.
- // Moving the base by 1 for each elapsed second is a good compromise between avoiding overlap
- // between allocation ranges and not reaching wrap around too soon.
- timespec ts{};
- clock_gettime(CLOCK_MONOTONIC, &ts);
- // zero ID has a special meaning, so start allocation at least at AUDIO_UNIQUE_ID_USE_MAX
- uint32_t movingBase = (uint32_t)std::max((long)1, ts.tv_sec);
- // unsigned instead of audio_unique_id_use_t, because ++ operator is unavailable for enum
- for (unsigned use = AUDIO_UNIQUE_ID_USE_UNSPECIFIED; use < AUDIO_UNIQUE_ID_USE_MAX; use++) {
- mNextUniqueIds[use] =
- ((use == AUDIO_UNIQUE_ID_USE_SESSION || use == AUDIO_UNIQUE_ID_USE_CLIENT) ?
- movingBase : 1) * AUDIO_UNIQUE_ID_USE_MAX;
- }
-
- #if 1
- // FIXME See bug 165702394 and bug 168511485
- const bool doLog = false;
- #else
- const bool doLog = property_get_bool("ro.test_harness", false);
- #endif
- if (doLog) {
- mLogMemoryDealer = new MemoryDealer(kLogMemorySize, "LogWriters",
- MemoryHeapBase::READ_ONLY);
- (void) pthread_once(&sMediaLogOnce, sMediaLogInit);
- }
-
- // reset battery stats.
- // if the audio service has crashed, battery stats could be left
- // in bad state, reset the state upon service start.
- BatteryNotifier::getInstance().noteResetAudio();
-
- mDevicesFactoryHal = DevicesFactoryHalInterface::create();
- mEffectsFactoryHal = EffectsFactoryHalInterface::create();
-
- mMediaLogNotifier->run("MediaLogNotifier");
- std::vector<pid_t> halPids;
- mDevicesFactoryHal->getHalPids(&halPids);
- TimeCheck::setAudioHalPids(halPids);
-
- // Notify that we have started (also called when audioserver service restarts)
- mediametrics::LogItem(mMetricsId)
- .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_CTOR)
- .record();
- }
C++ 中智能指针创建对象时,第一次创建会调用onFirstRef()函数,在本例中将调用 AudioFlinger::onFirstRef() 函数,
内容如下:frameworks/av/services/audioflinger/audioFlinger.cpp
- void AudioFlinger::onFirstRef()
- {
- Mutex::Autolock _l(mLock);
-
- /* TODO: move all this work into an Init() function */
- char val_str[PROPERTY_VALUE_MAX] = { 0 };
- if (property_get("ro.audio.flinger_standbytime_ms", val_str, NULL) >= 0) {
- uint32_t int_val;
- if (1 == sscanf(val_str, "%u", &int_val)) {
- mStandbyTimeInNsecs = milliseconds(int_val);
- ALOGI("Using %u mSec as standby time.", int_val);
- } else {
- mStandbyTimeInNsecs = kDefaultStandbyTimeInNsecs;
- ALOGI("Using default %u mSec as standby time.",
- (uint32_t)(mStandbyTimeInNsecs / 1000000));
- }
- }
-
- mMode = AUDIO_MODE_NORMAL;
-
- gAudioFlinger = this; // we are already refcounted, store into atomic pointer.
-
- mDevicesFactoryHalCallback = new DevicesFactoryHalCallbackImpl;
- mDevicesFactoryHal->setCallbackOnce(mDevicesFactoryHalCallback);
- }
至此 audioFlinger 对象构建完成
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。