1dcb346b7dc5b88c3e85db8a70bbd6a2fee8192b9Marco Nelissen/* 2dcb346b7dc5b88c3e85db8a70bbd6a2fee8192b9Marco Nelissen * Copyright (C) 2015 The Android Open Source Project 3dcb346b7dc5b88c3e85db8a70bbd6a2fee8192b9Marco Nelissen * 4dcb346b7dc5b88c3e85db8a70bbd6a2fee8192b9Marco Nelissen * Licensed under the Apache License, Version 2.0 (the "License"); 5dcb346b7dc5b88c3e85db8a70bbd6a2fee8192b9Marco Nelissen * you may not use this file except in compliance with the License. 6dcb346b7dc5b88c3e85db8a70bbd6a2fee8192b9Marco Nelissen * You may obtain a copy of the License at 7dcb346b7dc5b88c3e85db8a70bbd6a2fee8192b9Marco Nelissen * 8dcb346b7dc5b88c3e85db8a70bbd6a2fee8192b9Marco Nelissen * http://www.apache.org/licenses/LICENSE-2.0 9dcb346b7dc5b88c3e85db8a70bbd6a2fee8192b9Marco Nelissen * 10dcb346b7dc5b88c3e85db8a70bbd6a2fee8192b9Marco Nelissen * Unless required by applicable law or agreed to in writing, software 11dcb346b7dc5b88c3e85db8a70bbd6a2fee8192b9Marco Nelissen * distributed under the License is distributed on an "AS IS" BASIS, 12dcb346b7dc5b88c3e85db8a70bbd6a2fee8192b9Marco Nelissen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13dcb346b7dc5b88c3e85db8a70bbd6a2fee8192b9Marco Nelissen * See the License for the specific language governing permissions and 14dcb346b7dc5b88c3e85db8a70bbd6a2fee8192b9Marco Nelissen * limitations under the License. 15dcb346b7dc5b88c3e85db8a70bbd6a2fee8192b9Marco Nelissen */ 16dcb346b7dc5b88c3e85db8a70bbd6a2fee8192b9Marco Nelissen 17dcb346b7dc5b88c3e85db8a70bbd6a2fee8192b9Marco Nelissen#define LOG_TAG "audioserver" 18dcb346b7dc5b88c3e85db8a70bbd6a2fee8192b9Marco Nelissen//#define LOG_NDEBUG 0 19dcb346b7dc5b88c3e85db8a70bbd6a2fee8192b9Marco Nelissen 20ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten#include <fcntl.h> 21ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten#include <sys/prctl.h> 22ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten#include <sys/wait.h> 23ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten#include <cutils/properties.h> 24ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten 25dcb346b7dc5b88c3e85db8a70bbd6a2fee8192b9Marco Nelissen#include <binder/IPCThreadState.h> 26dcb346b7dc5b88c3e85db8a70bbd6a2fee8192b9Marco Nelissen#include <binder/ProcessState.h> 27dcb346b7dc5b88c3e85db8a70bbd6a2fee8192b9Marco Nelissen#include <binder/IServiceManager.h> 28dcb346b7dc5b88c3e85db8a70bbd6a2fee8192b9Marco Nelissen#include <utils/Log.h> 29dcb346b7dc5b88c3e85db8a70bbd6a2fee8192b9Marco Nelissen 30dcb346b7dc5b88c3e85db8a70bbd6a2fee8192b9Marco Nelissen// from LOCAL_C_INCLUDES 31dcb346b7dc5b88c3e85db8a70bbd6a2fee8192b9Marco Nelissen#include "AudioFlinger.h" 32dcb346b7dc5b88c3e85db8a70bbd6a2fee8192b9Marco Nelissen#include "AudioPolicyService.h" 33ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten#include "MediaLogService.h" 34dcb346b7dc5b88c3e85db8a70bbd6a2fee8192b9Marco Nelissen#include "RadioService.h" 35dcb346b7dc5b88c3e85db8a70bbd6a2fee8192b9Marco Nelissen#include "SoundTriggerHwService.h" 36dcb346b7dc5b88c3e85db8a70bbd6a2fee8192b9Marco Nelissen 37dcb346b7dc5b88c3e85db8a70bbd6a2fee8192b9Marco Nelissenusing namespace android; 38dcb346b7dc5b88c3e85db8a70bbd6a2fee8192b9Marco Nelissen 39ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kastenint main(int argc __unused, char **argv) 40dcb346b7dc5b88c3e85db8a70bbd6a2fee8192b9Marco Nelissen{ 41dcb346b7dc5b88c3e85db8a70bbd6a2fee8192b9Marco Nelissen signal(SIGPIPE, SIG_IGN); 42dcb346b7dc5b88c3e85db8a70bbd6a2fee8192b9Marco Nelissen 43ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten bool doLog = (bool) property_get_bool("ro.test_harness", 0); 44ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten 45ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten pid_t childPid; 46ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten // FIXME The advantage of making the process containing media.log service the parent process of 47ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten // the process that contains the other audio services, is that it allows us to collect more 48ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten // detailed information such as signal numbers, stop and continue, resource usage, etc. 49ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten // But it is also more complex. Consider replacing this by independent processes, and using 50ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten // binder on death notification instead. 51ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten if (doLog && (childPid = fork()) != 0) { 52ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten // media.log service 53ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten //prctl(PR_SET_NAME, (unsigned long) "media.log", 0, 0, 0); 54ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten // unfortunately ps ignores PR_SET_NAME for the main thread, so use this ugly hack 55ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten strcpy(argv[0], "media.log"); 56ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten sp<ProcessState> proc(ProcessState::self()); 57ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten MediaLogService::instantiate(); 58ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten ProcessState::self()->startThreadPool(); 599c0b3a300956162b9e70d74db69d9bbb87868eb1Eric Laurent IPCThreadState::self()->joinThreadPool(); 60ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten for (;;) { 61ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten siginfo_t info; 62ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten int ret = waitid(P_PID, childPid, &info, WEXITED | WSTOPPED | WCONTINUED); 63ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten if (ret == EINTR) { 64ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten continue; 65ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten } 66ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten if (ret < 0) { 67ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten break; 68ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten } 69ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten char buffer[32]; 70ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten const char *code; 71ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten switch (info.si_code) { 72ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten case CLD_EXITED: 73ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten code = "CLD_EXITED"; 74ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten break; 75ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten case CLD_KILLED: 76ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten code = "CLD_KILLED"; 77ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten break; 78ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten case CLD_DUMPED: 79ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten code = "CLD_DUMPED"; 80ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten break; 81ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten case CLD_STOPPED: 82ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten code = "CLD_STOPPED"; 83ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten break; 84ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten case CLD_TRAPPED: 85ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten code = "CLD_TRAPPED"; 86ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten break; 87ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten case CLD_CONTINUED: 88ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten code = "CLD_CONTINUED"; 89ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten break; 90ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten default: 91ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten snprintf(buffer, sizeof(buffer), "unknown (%d)", info.si_code); 92ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten code = buffer; 93ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten break; 94ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten } 95ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten struct rusage usage; 96ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten getrusage(RUSAGE_CHILDREN, &usage); 97ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten ALOG(LOG_ERROR, "media.log", "pid %d status %d code %s user %ld.%03lds sys %ld.%03lds", 98ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten info.si_pid, info.si_status, code, 99ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten usage.ru_utime.tv_sec, usage.ru_utime.tv_usec / 1000, 100ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten usage.ru_stime.tv_sec, usage.ru_stime.tv_usec / 1000); 101ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten sp<IServiceManager> sm = defaultServiceManager(); 102ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten sp<IBinder> binder = sm->getService(String16("media.log")); 103ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten if (binder != 0) { 104ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten Vector<String16> args; 105ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten binder->dump(-1, args); 106ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten } 107ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten switch (info.si_code) { 108ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten case CLD_EXITED: 109ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten case CLD_KILLED: 110ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten case CLD_DUMPED: { 111ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten ALOG(LOG_INFO, "media.log", "exiting"); 112ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten _exit(0); 113ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten // not reached 114ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten } 115ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten default: 116ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten break; 117ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten } 118ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten } 119ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten } else { 120ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten // all other services 121ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten if (doLog) { 122ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten prctl(PR_SET_PDEATHSIG, SIGKILL); // if parent media.log dies before me, kill me also 123ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten setpgid(0, 0); // but if I die first, don't kill my parent 124ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten } 125ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten sp<ProcessState> proc(ProcessState::self()); 126ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten sp<IServiceManager> sm = defaultServiceManager(); 127ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten ALOGI("ServiceManager: %p", sm.get()); 128ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten AudioFlinger::instantiate(); 129ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten AudioPolicyService::instantiate(); 130ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten RadioService::instantiate(); 131ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten SoundTriggerHwService::instantiate(); 132ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten ProcessState::self()->startThreadPool(); 133ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten IPCThreadState::self()->joinThreadPool(); 134ae0cff1d48b2cd10aeff9627398faf684894eeceGlenn Kasten } 135dcb346b7dc5b88c3e85db8a70bbd6a2fee8192b9Marco Nelissen} 136