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