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