一、 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 通过反射的方式获取系统的各种服务,
由此可以对安卓系统服务概念理解会更加深刻。
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 ,启动多媒体服务。
on property:init.svc.media=*setprop init.svc.mediadrm ${init.svc.media}service media /system/bin/mediaserverclass mainuser mediagroup audio camera inet net_bt net_bt_admin net_bw_acct drmrpc mediadrmioprio rt 4task_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-serverclass mainsocket zygote stream 660 root systemonrestart write /sys/android_power/request_state wakeonrestart write /sys/power/state ononrestart restart audioserver ## 启动 audioserver 服务onrestart restart cameraserver ## 启动 cameraserver 服务onrestart restart mediaonrestart restart netdwritepid /dev/cpuset/foreground/tasks
frameworks/av/media/audioserver/main_audioserver.cpp 此程序是入口函数
int main(int argc __unused, char **argv)
{// TODO: update with refined parameterslimitProcessMemory("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 168511485const bool doLog = false;
#elsebool doLog = (bool) property_get_bool("ro.test_harness", 0);
#endifpid_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 hackstrcpy(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 servicesif (doLog) {prctl(PR_SET_PDEATHSIG, SIGKILL); // if parent media.log dies before me, kill me alsosetpgid(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_MAXuint32_t movingBase = (uint32_t)std::max((long)1, ts.tv_sec);// unsigned instead of audio_unique_id_use_t, because ++ operator is unavailable for enumfor (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 168511485const bool doLog = false;
#elseconst bool doLog = property_get_bool("ro.test_harness", false);
#endifif (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 对象构建完成