/* * Copyright (C) 2015 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define LOG_TAG "audioserver" //#define LOG_NDEBUG 0 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // from include_dirs #include "AudioFlinger.h" #include "AudioPolicyService.h" #include "AAudioService.h" #include "utility/AAudioUtilities.h" #include "MediaLogService.h" using namespace android; using android::media::audio::common::AudioMMapPolicy; using android::media::audio::common::AudioMMapPolicyInfo; using android::media::audio::common::AudioMMapPolicyType; int main(int argc __unused, char **argv) { ALOGD("%s: starting", __func__); const auto startTime = std::chrono::steady_clock::now(); // 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 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; 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 sm = defaultServiceManager(); sp binder = sm->getService(String16("media.log")); if (binder != 0) { Vector 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*/); // Ensure threads for possible callbacks. Note that get_audio_flinger() does // this automatically when called from AudioPolicy, but we do this anyways here. ProcessState::self()->startThreadPool(); // Instantiating AudioFlinger (making it public, e.g. through ::initialize()) // and then instantiating AudioPolicy (and making it public) // leads to situations where AudioFlinger is accessed remotely before // AudioPolicy is initialized. Not only might this // cause inaccurate results, but if AudioPolicy has slow audio HAL // initialization, it can cause a TimeCheck abort to occur on an AudioFlinger // call which tries to access AudioPolicy. // // We create AudioFlinger and AudioPolicy locally then make it public to ServiceManager. // This requires both AudioFlinger and AudioPolicy to be in-proc. // const auto af = sp::make(); const auto afAdapter = sp::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::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 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); // 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. // If we cannot get audio flinger here, there must be some serious problems. In that case, // attempting to call audio flinger on a null pointer could make the process crash // and attract attentions. std::vector policyInfos; status_t status = sp::cast(af)->getMmapPolicyInfos( AudioMMapPolicyType::DEFAULT, &policyInfos); // Initialize aaudio service when querying mmap policy succeeds and // any of the policy supports MMAP. 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(); using FloatMillis = std::chrono::duration; const float timeTaken = std::chrono::duration_cast( endTime - startTime).count(); ALOGI("%s: initialization done in %.3f ms, joining thread pool", __func__, timeTaken); IPCThreadState::self()->joinThreadPool(); } }