天天看點

Android Audio:main_audioserver.cpp中的main()函數啟動流程

Android Audio:main_audioserver.cpp中的main()函數啟動流程
Android Audio:main_audioserver.cpp中的main()函數啟動流程
Android Audio:main_audioserver.cpp中的main()函數啟動流程
int main(int argc __unused, char **argv)
{
    // 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);

    bool doLog = (bool) property_get_bool("ro.test_harness", 0);

    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<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 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*/);
        sp<ProcessState> proc(ProcessState::self());
        sp<IServiceManager> sm = defaultServiceManager();
        ALOGI("ServiceManager: %p", sm.get());
        AudioFlinger::instantiate();
        AudioPolicyService::instantiate();
#ifdef VRAUDIOSERVICE_ENABLE
        VRAudioServiceNative::instantiate();
#endif

        // 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();
        }

        SoundTriggerHwService::instantiate();
        ProcessState::self()->startThreadPool();
        IPCThreadState::self()->joinThreadPool();
    }
}
           

首先來依次看main()函數做了什麼事情。

首先限制程序的記憶體。

在Socket 通信過程中,如果收到SIGPIPE信号,導緻程序退出。為了避免程序退出, 設定捕獲SIGPIPE信号,或者忽略它, 給它設定 SIG_IGN 處理,保證 server 能夠正常進行。

Android Audio:main_audioserver.cpp中的main()函數啟動流程

\android\system\core\libcutils\include\cutils\properties.h

傳回一個強制轉換為的布爾值。如果屬性未設定,則傳回默值,0代表false。

Android Audio:main_audioserver.cpp中的main()函數啟動流程

建立子線程,執行個體化 ProcessState,打開 /dev/binder 驅動,儲存 binder 裝置的檔案描述符,用于後續的 binder 通信,在 ProcessState 中建立一個線程池,最後将目前線程加入線程池中。

Android Audio:main_audioserver.cpp中的main()函數啟動流程

首先來看第一個,執行個體化ProcessState.

\android\frameworks\native\libs\binder\include\binder\ProcessState.h

Android Audio:main_audioserver.cpp中的main()函數啟動流程

\android\frameworks\native\libs\binder\ProcessState.cpp

打開 /dev/binder 驅動

Android Audio:main_audioserver.cpp中的main()函數啟動流程

mmap将一個檔案或者其它對象映射進記憶體。檔案被映射到多個頁上,如果檔案的大小不是所有頁的大小之和,最後一個頁不被使用的空間将會清零。提供一大塊虛拟位址空間來接收事務。

Android Audio:main_audioserver.cpp中的main()函數啟動流程

接着看建立線程池。

Android Audio:main_audioserver.cpp中的main()函數啟動流程

makeBinderThreadName()原子設定獲得字元串,建立線程并運作。

Android Audio:main_audioserver.cpp中的main()函數啟動流程

Explicit限制隻能被顯式調用。

Android Audio:main_audioserver.cpp中的main()函數啟動流程

最後,加入線程。

android\frameworks\native\libs\binder\IPCThreadState.cpp

Android Audio:main_audioserver.cpp中的main()函數啟動流程

android\frameworks\native\libs\binder\include\binder\IPCThreadState.h

Android Audio:main_audioserver.cpp中的main()函數啟動流程

android\frameworks\native\libs\binder\Parcel.cpp

Android Audio:main_audioserver.cpp中的main()函數啟動流程

跳轉到此處。writeInterfaceToken是parcel第一次被調用的函數,

COMPILE_TIME_ASSERT_FUNCTION_SCOPE(PAD_SIZE(sizeof(T)) == sizeof(T));

是斷言,判斷讀寫時是否為4位元組對齊#define PAD_SIZE(s) (((s)+3)&~3)

Android Audio:main_audioserver.cpp中的main()函數啟動流程

最後看joinThreadPool的最後的一個函數。

Android Audio:main_audioserver.cpp中的main()函數啟動流程

talkWithDriver 要和驅動通信了,在這裡所有的資料又被一個新的結構體标記了,struct binder_write_read.為什麼是标記而不是取代,binder_write_read 僅僅描述了IPCThreadState 的兩個Parcel 大小,已經内部記憶體的位址。ioctl 調用BINDER_WRITE_READ 指令進入核心, 傳遞的參數是 struct binder_write_read。mIn 用來存放從核心的傳回資料。

status_t IPCThreadState::talkWithDriver(bool doReceive)
{
    if (mProcess->mDriverFD <= 0) {
        return -EBADF;
    }

    binder_write_read bwr;

    // Is the read buffer empty?
    const bool needRead = mIn.dataPosition() >= mIn.dataSize();

    // We don't want to write anything if we are still reading
    // from data left in the input buffer and the caller
    // has requested to read the next data.
    const size_t outAvail = (!doReceive || needRead) ? mOut.dataSize() : 0;

    bwr.write_size = outAvail;
    bwr.write_buffer = (uintptr_t)mOut.data();

    // This is what we'll read.
    if (doReceive && needRead) {
        bwr.read_size = mIn.dataCapacity();
        bwr.read_buffer = (uintptr_t)mIn.data();
    } else {
        bwr.read_size = 0;
        bwr.read_buffer = 0;
    }

    IF_LOG_COMMANDS() {
        TextOutput::Bundle _b(alog);
        if (outAvail != 0) {
            alog << "Sending commands to driver: " << indent;
            const void* cmds = (const void*)bwr.write_buffer;
            const void* end = ((const uint8_t*)cmds)+bwr.write_size;
            alog << HexDump(cmds, bwr.write_size) << endl;
            while (cmds < end) cmds = printCommand(alog, cmds);
            alog << dedent;
        }
        alog << "Size of receive buffer: " << bwr.read_size
            << ", needRead: " << needRead << ", doReceive: " << doReceive << endl;
    }

    // Return immediately if there is nothing to do.
    if ((bwr.write_size == 0) && (bwr.read_size == 0)) return NO_ERROR;

    bwr.write_consumed = 0;
    bwr.read_consumed = 0;
    status_t err;
    do {
        IF_LOG_COMMANDS() {
            alog << "About to read/write, write size = " << mOut.dataSize() << endl;
        }
#if defined(__ANDROID__)
        if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)
            err = NO_ERROR;
        else
            err = -errno;
#else
        err = INVALID_OPERATION;
#endif
        if (mProcess->mDriverFD <= 0) {
            err = -EBADF;
        }
        IF_LOG_COMMANDS() {
            alog << "Finished read/write, write size = " << mOut.dataSize() << endl;
        }
    } while (err == -EINTR);

    IF_LOG_COMMANDS() {
        alog << "Our err: " << (void*)(intptr_t)err << ", write consumed: "
            << bwr.write_consumed << " (of " << mOut.dataSize()
                        << "), read consumed: " << bwr.read_consumed << endl;
    }

    if (err >= NO_ERROR) {
        if (bwr.write_consumed > 0) {
            if (bwr.write_consumed < mOut.dataSize())
                mOut.remove(0, bwr.write_consumed);
            else {
                mOut.setDataSize(0);
                processPostWriteDerefs();
            }
        }
        if (bwr.read_consumed > 0) {
            mIn.setDataSize(bwr.read_consumed);
            mIn.setDataPosition(0);
        }
        IF_LOG_COMMANDS() {
            TextOutput::Bundle _b(alog);
            alog << "Remaining data size: " << mOut.dataSize() << endl;
            alog << "Received commands from driver: " << indent;
            const void* cmds = mIn.data();
            const void* end = mIn.data() + mIn.dataSize();
            alog << HexDump(cmds, mIn.dataSize()) << endl;
            while (cmds < end) cmds = printReturnCommand(alog, cmds);
            alog << dedent;
        }
        return NO_ERROR;
    }

    return err;
}
           

最後傳回main()函數,看AF和APS的instantiate()

Android Audio:main_audioserver.cpp中的main()函數啟動流程
Android Audio:main_audioserver.cpp中的main()函數啟動流程

android\frameworks\av\media\audioserver\main_audioserver.cpp

Android Audio:main_audioserver.cpp中的main()函數啟動流程

frameworks\av\services\audioflinger\BinderService.h

Android Audio:main_audioserver.cpp中的main()函數啟動流程

開頭定義了一個模闆,是以走不同服務的對應的構造函數。

Android Audio:main_audioserver.cpp中的main()函數啟動流程

ps:暫時分析到此,AF和APS的instantiate()單獨分開分析。

Android Audio:main_audioserver.cpp中的main()函數啟動流程