一、 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
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 通过反射的方式获取系统的各种服务,
由此可以对安卓系统服务概念理解会更加深刻。
二、 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 ,启动多媒体服务。
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 是电话服务,不是本次讨论内容略过。
2.1> audioflinger 本地混音管理框架
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 对象构建完成