Android Media Service Binder Machine

 

 

 

1.   Frameworks/av/media/mediaserver/main_mediaserver.cpp

1.1      main

int main(int argc, char** argv)

{

    signal(SIGPIPE, SIG_IGN);

    char value[PROPERTY_VALUE_MAX];

    bool doLog =(property_get("ro.test_harness", value, "0") > 0)&& (atoi(value) == 1);

    pid_t childPid;

    // FIXME The advantage of making theprocess containing media.log service the parent process of

    // the process that contains all the otherreal services, is that it allows us to collect more

    // detailed information such as signalnumbers, stop and continue, resource usage, etc.

    // But it is also more complex.  Consider replacing this by independentprocesses, 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_NAMEfor the main thread, so use this ugly hack

        strcpy(argv[0], "media.log");

        sp<ProcessState>proc(ProcessState::self());

        MediaLogService::instantiate();

       ProcessState::self()->startThreadPool();

        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 mealso

            setpgid(0, 0);                      // but if I die first,don't kill my parent

        }

// 创建一个ProcessState对象实例

       sp<ProcessState> proc(ProcessState::self());

// MediaServer对于 ServiceManager来说,是个客户端,它需要向

// ServiceManager注册。调用 defaultServiceManager得到一个IServiceManager.

        sp<IServiceManager> sm =defaultServiceManager();

        ALOGI("ServiceManager: %p",sm.get());

// 初始化音频系统的AudioFlinger服务

        AudioFlinger::instantiate();

// MediaPlayer服务

        MediaPlayerService::instantiate();

// Camera服务

        CameraService::instantiate();

// AudioPolicy服务

        AudioPolicyService::instantiate();

// This anull function

        registerExtensions();

// Createa thread and join this thread into ThreadPool

       ProcessState::self()->startThreadPool();

// Joinself inot thread pool

       IPCThreadState::self()->joinThreadPool();

    }

}

 

 

 

 

 

 

 

 

 

 

 

 

 

2.  frameworks/native/libs/binder/ProcessState.cpp

2.1  ProcessState::self()

sp<ProcessState>ProcessState::self()

{

    Mutex::Autolock _l(gProcessMutex);

    if (gProcess != NULL) {

        return gProcess;

    }

    gProcess = newProcessState;

    return gProcess;

}

 

 2.2  ProcessState::self()

ProcessState::ProcessState()

    :mDriverFD(open_driver())

    , mVMStart(MAP_FAILED)

    , mManagesContexts(false)

    ,mBinderContextCheckFunc(NULL)

    ,mBinderContextUserData(NULL)

    ,mThreadPoolStarted(false)

    , mThreadPoolSeq(1)

{

    if (mDriverFD >= 0) {

        // XXX Ideally, thereshould be a specific define for whether we

        // have mmap (orwhether we could possibly have the kernel module

        // availabla).

#if !defined(HAVE_WIN32_IPC)

        // mmap the binder,providing a chunk of virtual address space to receive transactions.

        mVMStart = mmap(0,BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);

        if (mVMStart ==MAP_FAILED) {

            // *sigh*

            ALOGE("Using/dev/binder failed: unable to mmap transaction memory.\n");

            close(mDriverFD);

            mDriverFD = -1;

        }

#else

        mDriverFD = -1;

#endif

    }

 

   LOG_ALWAYS_FATAL_IF(mDriverFD < 0, "Binder driver could not beopened.  Terminating.");

}

 

2.3  open_driver()

static int open_driver()

{

    int fd =open("/dev/binder", O_RDWR);

    if (fd >= 0) {

        fcntl(fd, F_SETFD,FD_CLOEXEC);

        int vers;

        status_t result =ioctl(fd, BINDER_VERSION, &vers);

        if (result == -1) {

            ALOGE("Binderioctl to obtain version failed: %s", strerror(errno));

            close(fd);

            fd = -1;

        }

        if (result != 0 ||vers != BINDER_CURRENT_PROTOCOL_VERSION) {

            ALOGE("Binderdriver protocol does not match user space protocol!");

            close(fd);

            fd = -1;

        }

        size_t maxThreads =15;

        result = ioctl(fd,BINDER_SET_MAX_THREADS, &maxThreads);

        if (result == -1) {

            ALOGE("Binderioctl to set max threads failed: %s", strerror(errno));

        }

    } else {

        ALOGW("Opening'/dev/binder' failed: %s\n", strerror(errno));

    }

    return fd;

}

 

3.  frameworks/native/libs/binder/IServiceManager.cpp

3.1  defaultServiceManager ()

sp<IServiceManager> defaultServiceManager()

{

    if (gDefaultServiceManager!= NULL) return gDefaultServiceManager;

   

    {

        AutoMutex_l(gDefaultServiceManagerLock);

        if(gDefaultServiceManager == NULL) {

           gDefaultServiceManager = interface_cast<IServiceManager>(

               ProcessState::self()->getContextObject(NULL));

        }

    }

   

    returngDefaultServiceManager;

}

 

4.  frameworks/native/libs/binder/ProcessState.cpp

4.1  defaultServiceManager ()

sp<IBinder> ProcessState::getContextObject(constsp<IBinder>& caller)

{

    returngetStrongProxyForHandle(0);

}

4.2  ProcessState::getStrongProxyForHandle

sp<IBinder> ProcessState::getStrongProxyForHandle(int32_thandle)

{

    sp<IBinder> result;

 

    AutoMutex _l(mLock);

 

    handle_entry* e = lookupHandleLocked(handle);

 

    if (e != NULL) {

        // We need to create anew BpBinder if there isn't currently one, OR we

        // are unable toacquire a weak reference on this current one. 

// See comment

        // ingetWeakProxyForHandle() for more info about this.

        IBinder* b =e->binder;

        if (b == NULL ||!e->refs->attemptIncWeak(this)) {

           b = new BpBinder(handle);

            e->binder = b;

            if (b) e->refs= b->getWeakRefs();

            result = b;

        } else {

            // This little bitof nastyness is to allow us to add a primary

            // reference tothe remote proxy when this team doesn't have one

            // but anotherteam is sending the handle to us.

           result.force_set(b);

            e->refs->decWeak(this);

        }

    }

 

    return result;

}

 

 

4.3  BpBinder and BBinder

BpBinder and BBinder all inherit from IBinder, BpBinder is clientend, BBinder is service end in light of binder communication. BpBinder isone-one correspondent with BBinder, BpBinder identify BBinder by handle.

 

Frameworks/native/libs/binder/BpBinder.cpp

BpBinder::BpBinder(int32_t handle)

    : mHandle(handle)          // handle is 0

    , mAlive(1)

    , mObitsSent(0)

    , mObituaries(NULL)

{

    ALOGV("CreatingBpBinder %p handle %d\n", this, mHandle);

 

   extendObjectLifetime(OBJECT_LIFETIME_WEAK);

   IPCThreadState::self()->incWeakHandle(handle);

}

4.4 BpServiceManager and BnServiceManager(IServiceManager)

In

gDefaultServiceManager = interface_cast<IServiceManager>(

               ProcessState::self()->getContextObject(NULL));

ProcessState::self()->getContextObject(NULL)返回一个BpBinder对象,然后interface_castBpBinder对象生成了一个BpServiceManager对象。 Interface_cast定义与实现在frameworks/native/include/binder/IInterface.h

 

从图中可以看出, BnServiceManager直接继承于BBinder 。而BpServiceManager不是如此。BpServiceManager是利用一个BpBinder的成员变量指针mRemote而与Binder通讯的。

 

 

 

Frameworks/native/libs/binder/IServiceManager.cpp

    BpServiceManager(constsp<IBinder>& impl)

        :BpInterface<IServiceManager>(impl)

    {

    }

 

Frameworks/native/include/binder/IInterface.h

template<typename INTERFACE>

inline BpInterface<INTERFACE>::BpInterface(constsp<IBinder>& remote)

    : BpRefBase(remote)

{

}

 

Frameworks/native/libs/binder/Binder.cpp

BpRefBase::BpRefBase(const sp<IBinder>& o) 

    :mRemote(o.get()), mRefs(NULL), mState(0)

{

    extendObjectLifetime(OBJECT_LIFETIME_WEAK);

 

    if (mRemote) {

       mRemote->incStrong(this);          // Removed on first IncStrong().

        mRefs =mRemote->createWeak(this);  // Heldfor our entire lifetime.

    }

}

从上面的可以看到ProcessState::self()->getContextObject(NULL)返回一个BpBinder对象,再经过interface_cast生成BpServiceManager,并把BpBinder赋给BpServiceManager的成员变量mRemote.

defaultServiceManager我们得到了两个对象,一个BpBinder,其handle0一个BpServiceManager对象,mRemote指向BpBinder对象。

5.  frameworks/native/include/binder/BindServer.h

5.1  AudioFlinger::instantiate()

AudioFlinger inherit from BinderService, and no rewritinginstantiate of BinderService.

Therefore call BinderService::instantiate()

namespaceandroid {

 

template<typenameSERVICE>

classBinderService

{

public:

    static status_tpublish(bool allowIsolated = false) {

       sp<IServiceManager> sm(defaultServiceManager());

       returnsm->addService(

               String16(SERVICE::getServiceName()),

               newSERVICE(), allowIsolated);

    }

 

    static void publishAndJoinThreadPool(boolallowIsolated = false) {

        sp<IServiceManager>sm(defaultServiceManager());

        sm->addService(

               String16(SERVICE::getServiceName()),

                new SERVICE(), allowIsolated);

       ProcessState::self()->startThreadPool();

        ProcessState::self()->giveThreadPoolName();

       IPCThreadState::self()->joinThreadPool();

    }

 

    static voidinstantiate() { publish(); }

 

    static status_t shutdown() {

        return NO_ERROR;

    }

};

 

 

}; // namespace android

 

6.   frameworks/av/media/libmediaplayerservice/MediaPlayerService.cpp

6.1   MediaPlayerService::instantiate

voidMediaPlayerService::instantiate() { 

//注意:defaultServiceManager返回的是一个BpServiceManager对象

    defaultServiceManager()->addService(

            String16("media.player"),new MediaPlayerService());

}

8.  详述。

 

7.  frameworks/native/include/binder/BindServer.h

7.1  CameraService::instantiate()

5.1  AudioFlinger::instantiate()

7.2  AudioPolicyService::instantiate()

5.1  AudioFlinger::instantiate()

 

8   MediaPlayerService::instantiate()

8.1  MediaPlayerService::instantiate() 

// frameworks/av/media/libmediaplayerservice/MediaPlayerService.cpp

voidMediaPlayerService::instantiate() { 

//注意:defaultServiceManager返回的是一个BpServiceManager对象

    defaultServiceManager()->addService(

            String16("media.player"),new MediaPlayerService());

}

 

8.2  BpServiceManager:: addService () 

// frameworks/native/libs/binder/IServiceManager.cpp

    virtual status_t addService(constString16& name, const sp<IBinder>& service,

            bool allowIsolated)

    {

        Parcel data, reply;

       data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());

        data.writeString16(name);

        data.writeStrongBinder(service);

        data.writeInt32(allowIsolated ? 1 : 0);

        status_t err =remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);

        return err == NO_ERROR ?reply.readExceptionCode() : err;

}

 

8.3  BpBinder::transact () 

前面已经提过, BpServiceManagermRemote成员变量指向一个BpBinder对象,而remote()就是返回mRemote.

frameworks/native/libs/binder/BpBinder.cpp

status_tBpBinder::transact(

    uint32_t code, const Parcel& data,Parcel* reply, uint32_t flags)

{

    // Once a binder has died, it will nevercome back to life.

    if (mAlive) {

       status_t status= IPCThreadState::self()->transact(

           mHandle,code, data, reply, flags);

        if (status == DEAD_OBJECT) mAlive = 0;

        return status;

    }

 

    return DEAD_OBJECT;

}

 

8.4  IPCThreadState::transact () 

Frameworks/native/libs/binder/IPCThreadState.cpp

status_tIPCThreadState::transact(int32_t handle,

                                  uint32_t code,const Parcel& data,

                                  Parcel*reply, uint32_t flags)

{

    status_t err = data.errorCheck();

 

    flags |= TF_ACCEPT_FDS;

 

    IF_LOG_TRANSACTIONS() {

        TextOutput::Bundle _b(alog);

        alog << "BC_TRANSACTION thr" << (void*)pthread_self() << " / hand "

            << handle << " /code " << TypeCode(code) << ": "

            << indent << data<< dedent << endl;

    }

   

    if (err == NO_ERROR) {

        LOG_ONEWAY(">>>> SEND frompid %d uid %d %s", getpid(), getuid(),

            (flags & TF_ONE_WAY) == 0 ?"READ REPLY" : "ONE WAY");

       err =writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);

    }

   

    if (err != NO_ERROR) {

        if (reply) reply->setError(err);

        return (mLastError = err);

    }

   

    if ((flags & TF_ONE_WAY) == 0) {

        #if 0

        if (code == 4) { // relayout

           ALOGI(">>>>>> CALLING transaction 4");

        } else {

           ALOGI(">>>>>> CALLING transaction %d",code);

        }

        #endif

        if (reply) {

            err = waitForResponse(reply);

        } else {

            Parcel fakeReply;

            err =waitForResponse(&fakeReply);

        }

        #if 0

        if (code == 4) { // relayout

           ALOGI("<<<<<< RETURNING transaction 4");

        } else {

           ALOGI("<<<<<< RETURNING transaction %d",code);

        }

        #endif

       

        IF_LOG_TRANSACTIONS() {

            TextOutput::Bundle _b(alog);

            alog << "BR_REPLY thr" << (void*)pthread_self() << " / hand "

                << handle <<": ";

            if (reply) alog << indent<< *reply << dedent << endl;

            else alog << "(nonerequested)" << endl;

        }

    } else {

        err = waitForResponse(NULL, NULL);

    }

   

    return err;

}

 

8.5  MediaPlayerService::MediaPlayerService () 

Frameworks/av/media/libmediaplayerservice/MediaPlayerService.cpp

MediaPlayerService::MediaPlayerService()

{

    ALOGV("MediaPlayerServicecreated");

    mNextConnId = 1;

 

    mBatteryAudio.refCount = 0;

    for (int i = 0; i < NUM_AUDIO_DEVICES;i++) {

        mBatteryAudio.deviceOn[i] = 0;

        mBatteryAudio.lastTime[i] = 0;

        mBatteryAudio.totalTime[i] = 0;

    }

    // speaker is on by default

    mBatteryAudio.deviceOn[SPEAKER] = 1;

 

    MediaPlayerFactory::registerBuiltinFactories();

}

 

8.5  MediaPlayerFactory::registerBuiltinFactories()

Frameworks/av/media/libmediaplayerservice/MediaPlayerFactory.cpp

voidMediaPlayerFactory::registerBuiltinFactories() {

    Mutex::Autolock lock_(&sLock);

 

    if (sInitComplete)

        return;

 

   registerFactory_l(new StagefrightPlayerFactory(), STAGEFRIGHT_PLAYER);

   registerFactory_l(new NuPlayerFactory(), NU_PLAYER);

   registerFactory_l(new SonivoxPlayerFactory(), SONIVOX_PLAYER);

   registerFactory_l(new TestPlayerFactory(), TEST_PLAYER);

 

    sInitComplete = true;

}

 

status_tMediaPlayerFactory::registerFactory_l(IFactory* factory,

                                              player_type type) {

    if (NULL == factory) {

        ALOGE("Failed to registerMediaPlayerFactory of type %d, factory is"

              " NULL.", type);

        return BAD_VALUE;

    }

 

    if (sFactoryMap.indexOfKey(type) >= 0) {

        ALOGE("Failed to registerMediaPlayerFactory of type %d, type is"

              " already registered.",type);

        return ALREADY_EXISTS;

    }

 

    if (sFactoryMap.add(type, factory) < 0){

        ALOGE("Failed to registerMediaPlayerFactory of type %d, failed to add"

              " to map.", type);

        return UNKNOWN_ERROR;

    }

 

    return OK;

}

 

9   Binder Communication Layer

9.1   BpBinder::transact ()

9.2   IPCThreadState::transact()

9.3   IPCThreadState::writeTransactionData()

status_tIPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags,

    int32_t handle, uint32_t code, constParcel& data, status_t* statusBuffer)

{

    binder_transaction_data tr;

 

   tr.target.handle =handle;  // handle 标识目的端,其中0标识ServiceManager

    tr.code = code;

    tr.flags = binderFlags;

    tr.cookie = 0;

    tr.sender_pid = 0;

    tr.sender_euid = 0;

   

    const status_t err = data.errorCheck();

    if (err == NO_ERROR) {

        tr.data_size = data.ipcDataSize();

        tr.data.ptr.buffer = data.ipcData();

        tr.offsets_size =data.ipcObjectsCount()*sizeof(size_t);

        tr.data.ptr.offsets =data.ipcObjects();

    } else if (statusBuffer) {

        tr.flags |= TF_STATUS_CODE;

        *statusBuffer = err;

        tr.data_size = sizeof(status_t);

        tr.data.ptr.buffer = statusBuffer;

        tr.offsets_size = 0;

        tr.data.ptr.offsets = NULL;

    } else {

        return (mLastError = err);

    }

 

   // mIn, mOut是连个Parcel对象,发送和接收命令缓冲区。

   // 每个IPCThreadState都有一个mIn, mOutmIn是用来接收从binder设备

//来的数据,而mOut是用来存储发往binder设备的数据。

//写命令到缓冲区

    mOut.writeInt32(cmd);

    mOut.write(&tr, sizeof(tr));

   

    return NO_ERROR;

}

 

9.4   IPCThreadState::waitForResponse

发送请求与接收响应

status_tIPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)

{

    int32_t cmd;

    int32_t err;

 

    while (1) {

       if((err=talkWithDriver()) < NO_ERROR) break;

        err = mIn.errorCheck();

        if (err < NO_ERROR) break;

        if (mIn.dataAvail() == 0) continue;

       

        cmd = mIn.readInt32();

       

        IF_LOG_COMMANDS() {

            alog << "ProcessingwaitForResponse Command: "

                << getReturnString(cmd)<< endl;

        }

 

        switch (cmd) {

        case BR_TRANSACTION_COMPLETE:

            if (!reply &&!acquireResult) goto finish;

            break;

       

        case BR_DEAD_REPLY:

            err = DEAD_OBJECT;

            goto finish;

 

        case BR_FAILED_REPLY:

            err = FAILED_TRANSACTION;

            goto finish;

       

        case BR_ACQUIRE_RESULT:

            {

                ALOG_ASSERT(acquireResult !=NULL, "Unexpected brACQUIRE_RESULT");

                const int32_t result =mIn.readInt32();

                if (!acquireResult) continue;

                *acquireResult = result ?NO_ERROR : INVALID_OPERATION;

            }

            goto finish;

       

        case BR_REPLY:

            {

                binder_transaction_data tr;

                err = mIn.read(&tr,sizeof(tr));

                ALOG_ASSERT(err == NO_ERROR,"Not enough command data for brREPLY");

                if (err != NO_ERROR) gotofinish;

 

                if (reply) {

                    if ((tr.flags &TF_STATUS_CODE) == 0) {

                       reply->ipcSetDataReference(

                           reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),

                            tr.data_size,

                            reinterpret_cast<constsize_t*>(tr.data.ptr.offsets),

                           tr.offsets_size/sizeof(size_t),

                            freeBuffer, this);

                    } else {

                        err =*static_cast<const status_t*>(tr.data.ptr.buffer);

                        freeBuffer(NULL,

                           reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),

                            tr.data_size,

                           reinterpret_cast<const size_t*>(tr.data.ptr.offsets),

                           tr.offsets_size/sizeof(size_t), this);

                    }

                } else {

                    freeBuffer(NULL,

                       reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),

                        tr.data_size,

                       reinterpret_cast<const size_t*>(tr.data.ptr.offsets),

                       tr.offsets_size/sizeof(size_t), this);

                    continue;

                }

            }

            goto finish;

 

        default:

           err =executeCommand(cmd);

            if (err != NO_ERROR) goto finish;

            break;

        }

    }

 

finish:

    if (err != NO_ERROR) {

        if (acquireResult) *acquireResult =err;

        if (reply) reply->setError(err);

        mLastError = err;

    }

   

    return err;

}

 

9.5   IPCThreadState:: talkWithDriver

status_tIPCThreadState::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 weare still reading

    // from data left in the input buffer andthe caller

    // has requested to read the next data.

    const size_t outAvail = (!doReceive ||needRead) ? mOut.dataSize() : 0;

   

    bwr.write_size = outAvail;

    bwr.write_buffer = (long unsignedint)mOut.data();

 

    // This is what we'll read.

    if (doReceive && needRead) {

        bwr.read_size = mIn.dataCapacity();

        bwr.read_buffer = (long unsignedint)mIn.data();

    } else {

        bwr.read_size = 0;

        bwr.read_buffer = 0;

    }

 

    IF_LOG_COMMANDS() {

        TextOutput::Bundle _b(alog);

        if (outAvail != 0) {

            alog << "Sendingcommands to driver: " << indent;

            const void* cmds = (constvoid*)bwr.write_buffer;

            const void* end = ((constuint8_t*)cmds)+bwr.write_size;

            alog << HexDump(cmds,bwr.write_size) << endl;

            while (cmds < end) cmds =printCommand(alog, cmds);

            alog << dedent;

        }

        alog << "Size of receivebuffer: " << bwr.read_size

            << ", needRead: "<< needRead << ", doReceive: " << doReceive<< endl;

    }

   

    // Return immediately if there is nothingto 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 toread/write, write size = " << mOut.dataSize() << endl;

        }

#ifdefined(HAVE_ANDROID_OS)

       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 << "Finishedread/write, write size = " << mOut.dataSize() << endl;

        }

    } while (err == -EINTR);

 

    IF_LOG_COMMANDS() {

        alog << "Our err: "<< (void*)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 <(ssize_t)mOut.dataSize())

                mOut.remove(0,bwr.write_consumed);

            else

                mOut.setDataSize(0);

        }

        if (bwr.read_consumed > 0) {

            mIn.setDataSize(bwr.read_consumed);

            mIn.setDataPosition(0);

        }

        IF_LOG_COMMANDS() {

            TextOutput::Bundle _b(alog);

            alog << "Remaining datasize: " << mOut.dataSize() << endl;

            alog << "Received commandsfrom 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;

}

 

9.6   IPCThreadState:: executeCommand

现在假设请求后得到回复响应

status_tIPCThreadState::executeCommand(int32_t cmd)

{

    BBinder* obj;

    RefBase::weakref_type* refs;

    status_t result = NO_ERROR;

   

    switch (cmd) {

    case BR_ERROR:

        result = mIn.readInt32();

        break;

       

    case BR_OK:

        break;

       

    case BR_ACQUIRE:

        refs =(RefBase::weakref_type*)mIn.readInt32();

        obj = (BBinder*)mIn.readInt32();

        ALOG_ASSERT(refs->refBase() == obj,

                   "BR_ACQUIRE: object %pdoes not match cookie %p (expected %p)",

                   refs, obj,refs->refBase());

        obj->incStrong(mProcess.get());

        IF_LOG_REMOTEREFS() {

            LOG_REMOTEREFS("BR_ACQUIREfrom driver on %p", obj);

            obj->printRefs();

        }

        mOut.writeInt32(BC_ACQUIRE_DONE);

        mOut.writeInt32((int32_t)refs);

        mOut.writeInt32((int32_t)obj);

        break;

       

    case BR_RELEASE:

        refs =(RefBase::weakref_type*)mIn.readInt32();

        obj = (BBinder*)mIn.readInt32();

        ALOG_ASSERT(refs->refBase() == obj,

                   "BR_RELEASE: object %pdoes not match cookie %p (expected %p)",

                   refs, obj,refs->refBase());

        IF_LOG_REMOTEREFS() {

            LOG_REMOTEREFS("BR_RELEASEfrom driver on %p", obj);

            obj->printRefs();

        }

        mPendingStrongDerefs.push(obj);

        break;

       

    case BR_INCREFS:

        refs =(RefBase::weakref_type*)mIn.readInt32();

        obj = (BBinder*)mIn.readInt32();

        refs->incWeak(mProcess.get());

        mOut.writeInt32(BC_INCREFS_DONE);

        mOut.writeInt32((int32_t)refs);

        mOut.writeInt32((int32_t)obj);

        break;

       

    case BR_DECREFS:

        refs =(RefBase::weakref_type*)mIn.readInt32();

        obj = (BBinder*)mIn.readInt32();

        // NOTE: This assertion is not valid,because the object may no

        // longer exist (thus the(BBinder*)cast above resulting in a different

        // memory address).

        //ALOG_ASSERT(refs->refBase() ==obj,

        //           "BR_DECREFS: object %p does notmatch cookie %p (expected %p)",

        //           refs, obj, refs->refBase());

        mPendingWeakDerefs.push(refs);

        break;

       

    case BR_ATTEMPT_ACQUIRE:

        refs =(RefBase::weakref_type*)mIn.readInt32();

        obj = (BBinder*)mIn.readInt32();

        

        {

            const bool success =refs->attemptIncStrong(mProcess.get());

            ALOG_ASSERT(success &&refs->refBase() == obj,

                      "BR_ATTEMPT_ACQUIRE: object %p does not match cookie %p (expected%p)",

                       refs, obj,refs->refBase());

           

            mOut.writeInt32(BC_ACQUIRE_RESULT);

            mOut.writeInt32((int32_t)success);

        }

        break;

   

    case BR_TRANSACTION:

        {

            binder_transaction_data tr;

            result = mIn.read(&tr,sizeof(tr));

            ALOG_ASSERT(result == NO_ERROR,

                "Not enough command datafor brTRANSACTION");

            if (result != NO_ERROR) break;

           

            Parcel buffer;

            buffer.ipcSetDataReference(

                reinterpret_cast<constuint8_t*>(tr.data.ptr.buffer),

                tr.data_size,

                reinterpret_cast<constsize_t*>(tr.data.ptr.offsets),

                tr.offsets_size/sizeof(size_t),freeBuffer, this);

           

            const pid_t origPid = mCallingPid;

            const uid_t origUid = mCallingUid;

           

            mCallingPid = tr.sender_pid;

            mCallingUid = tr.sender_euid;

            

            int curPrio =getpriority(PRIO_PROCESS, mMyThreadId);

            if (gDisableBackgroundScheduling) {

                if (curPrio >ANDROID_PRIORITY_NORMAL) {

                    // We have inherited areduced priority from the caller, but do not

                    // want to run in thatstate in this process.  The driver setour

                    // priority already (thoughnot our scheduling class), so bounce

                    // it back to the defaultbefore invoking the transaction.

                    setpriority(PRIO_PROCESS,mMyThreadId, ANDROID_PRIORITY_NORMAL);

                }

            } else {

                if (curPrio >=ANDROID_PRIORITY_BACKGROUND) {

                    // We want to use theinherited priority from the caller.

                    // Ensure this thread is inthe background scheduling class,

                    // since the driver won'tmodify scheduling classes for us.

                    // The scheduling group isreset to default by the caller

                    // once this method returns afterthe transaction is complete.

                   set_sched_policy(mMyThreadId, SP_BACKGROUND);

                }

            }

 

            //ALOGI(">>>>TRANSACT from pid %d uid %d\n", mCallingPid, mCallingUid);

           

            Parcel reply;

            IF_LOG_TRANSACTIONS() {

                TextOutput::Bundle _b(alog);

                alog <<"BR_TRANSACTION thr " << (void*)pthread_self()

                    << " / obj" << tr.target.ptr << " / code "

                    << TypeCode(tr.code)<< ": " << indent << buffer

                    << dedent <<endl

                    << "Data addr ="

                    <<reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer)

                    << ", offsets addr="

                    <<reinterpret_cast<const size_t*>(tr.data.ptr.offsets) << endl;

            }

            if (tr.target.ptr) {

                //here, b can be CameraService object etc.

               sp<BBinder> b((BBinder*)tr.cookie);

               conststatus_t error = b->transact(tr.code, buffer, &reply, tr.flags);

                if (error < NO_ERROR)reply.setError(error);

            } else {

                const status_t error =the_context_object->transact(tr.code, buffer, &reply, tr.flags);

                if (error < NO_ERROR)reply.setError(error);

            }

           

            //ALOGI("<<<<TRANSACT from pid %d restore pid %d uid %d\n",

            //     mCallingPid, origPid, origUid);

           

            if ((tr.flags & TF_ONE_WAY) ==0) {

                LOG_ONEWAY("Sending replyto %d!", mCallingPid);

                sendReply(reply, 0);

            } else {

                LOG_ONEWAY("NOT sendingreply to %d!", mCallingPid);

            }

           

            mCallingPid = origPid;

            mCallingUid = origUid;

 

            IF_LOG_TRANSACTIONS() {

                TextOutput::Bundle _b(alog);

                alog << "BC_REPLYthr " << (void*)pthread_self() << " / obj "

                    << tr.target.ptr<< ": " << indent << reply << dedent <<endl;

            }

           

        }

        break;

   

    case BR_DEAD_BINDER:

        {

            BpBinder *proxy =(BpBinder*)mIn.readInt32();

            proxy->sendObituary();

           mOut.writeInt32(BC_DEAD_BINDER_DONE);

            mOut.writeInt32((int32_t)proxy);

        } break;

       

    case BR_CLEAR_DEATH_NOTIFICATION_DONE:

        {

            BpBinder *proxy =(BpBinder*)mIn.readInt32();

            proxy->getWeakRefs()->decWeak(proxy);

        } break;

       

    case BR_FINISHED:

        result = TIMED_OUT;

        break;

       

    case BR_NOOP:

        break;

       

    case BR_SPAWN_LOOPER:

        mProcess->spawnPooledThread(false);

        break;

        

    default:

        printf("*** BAD COMMAND %dreceived from Binder driver\n", cmd);

        result = UNKNOWN_ERROR;

        break;

    }

 

    if (result != NO_ERROR) {

        mLastError = result;

    }

   

    return result;

}


 

 

 

ServiceManager 分析

1.   Main()

Frameworks/native/cmds/servicesmanager/Service_manager.c

 

static struct {

   unsigned uid;

   const char *name;

} allowed[] = {

    {AID_MEDIA, "media.audio_flinger" },

    {AID_MEDIA, "media.log" },

    {AID_MEDIA, "media.player" },

    {AID_MEDIA, "media.camera" },

    {AID_MEDIA, "media.audio_policy" },

    {AID_DRM,   "drm.drmManager" },

    {AID_NFC,   "nfc" },

    {AID_BLUETOOTH, "bluetooth" },

    {AID_RADIO, "radio.phone" },

    {AID_RADIO, "radio.sms" },

    {AID_RADIO, "radio.phonesubinfo" },

    {AID_RADIO, "radio.simphonebook" },

/* TODO: remove after phone services areupdated: */

    {AID_RADIO, "phone" },

    {AID_RADIO, "sip" },

    {AID_RADIO, "isms" },

    {AID_RADIO, "iphonesubinfo" },

    {AID_RADIO, "simphonebook" },

    {AID_MEDIA, "common_time.clock" },

    {AID_MEDIA, "common_time.config" },

    {AID_KEYSTORE, "android.security.keystore" },

};

 

int main(int argc, char **argv)

{

   struct binder_state *bs;

   void *svcmgr = BINDER_SERVICE_MANAGER;

 

   bs = binder_open(128*1024);

 

   if (binder_become_context_manager(bs)) {

       ALOGE("cannot become context manager (%s)\n",strerror(errno));

       return -1;

    }

 

   svcmgr_handle = svcmgr;

   binder_loop(bs, svcmgr_handler);

   return 0;

}

 

2.   binder_open ()

frameworks/native/cmds/servicemanager/binder.c

struct binder_state *binder_open(unsignedmapsize)

{

   struct binder_state *bs;

 

   bs = malloc(sizeof(*bs));

   if (!bs) {

       errno = ENOMEM;

       return 0;

    }

 

   bs->fd = open("/dev/binder", O_RDWR);

   if (bs->fd < 0) {

       fprintf(stderr,"binder: cannot open device (%s)\n",

                strerror(errno));

       goto fail_open;

    }

 

   bs->mapsize = mapsize;

   bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd,0);

   if (bs->mapped == MAP_FAILED) {

       fprintf(stderr,"binder: cannot map device (%s)\n",

                strerror(errno));

       goto fail_map;

    }

 

       /* TODO: check version */

 

   return bs;

 

fail_map:

   close(bs->fd);

fail_open:

   free(bs);

   return 0;

}

 

 

 

3.   binder_become_context_manager ()

frameworks/native/cmds/servicemanager/binder.c

 

int binder_become_context_manager(structbinder_state *bs)

{

   return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);   // set self handleto 0

}

 

4.   binder_loop ()

frameworks/native/cmds/servicemanager/binder.c

 

void binder_loop(struct binder_state *bs,binder_handler func)

{

   int res;

   struct binder_write_read bwr;

   unsigned readbuf[32];

 

    bwr.write_size = 0;

   bwr.write_consumed = 0;

   bwr.write_buffer = 0;

   

   readbuf[0] = BC_ENTER_LOOPER;

   binder_write(bs, readbuf, sizeof(unsigned));

 

   for (;;) {

       bwr.read_size = sizeof(readbuf);

       bwr.read_consumed = 0;

        bwr.read_buffer = (unsigned) readbuf;

 

       res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);

 

       if (res < 0) {

           ALOGE("binder_loop: ioctl failed (%s)\n", strerror(errno));

           break;

       }

 

       res = binder_parse(bs, 0, readbuf, bwr.read_consumed, func);

       if (res == 0) {

           ALOGE("binder_loop: unexpected reply?!\n");

           break;

       }

       if (res < 0) {

           ALOGE("binder_loop: io error %d %s\n", res, strerror(errno));

           break;

       }

    }

}

 

 

 

5.   binder_parse ()

frameworks/native/cmds/servicemanager/binder.c

 

int binder_parse(struct binder_state *bs,struct binder_io *bio,

                 uint32_t *ptr, uint32_t size,binder_handler func)

{

   int r = 1;

   uint32_t *end = ptr + (size / 4);

 

   while (ptr < end) {

       uint32_t cmd = *ptr++;

#if TRACE

       fprintf(stderr,"%s:\n", cmd_name(cmd));

#endif

       switch(cmd) {

       case BR_NOOP:

           break;

       case BR_TRANSACTION_COMPLETE:

           break;

       case BR_INCREFS:

       case BR_ACQUIRE:

       case BR_RELEASE:

       case BR_DECREFS:

#if TRACE

           fprintf(stderr,"  %08x%08x\n", ptr[0], ptr[1]);

#endif

           ptr += 2;

           break;

       case BR_TRANSACTION: {

           struct binder_txn *txn = (void *) ptr;

           if ((end - ptr) * sizeof(uint32_t) < sizeof(struct binder_txn)) {

                ALOGE("parse: txn toosmall!\n");

                return -1;

           }

           binder_dump_txn(txn);

           if (func) {

                unsigned rdata[256/4];

                struct binder_io msg;

                struct binder_io reply;

                int res;

 

                bio_init(&reply, rdata,sizeof(rdata), 4);

                bio_init_from_txn(&msg,txn);

               res = func(bs, txn, &msg,&reply);

                binder_send_reply(bs,&reply, txn->data, res);

           }

           ptr += sizeof(*txn) / sizeof(uint32_t);

           break;

       }

       case BR_REPLY: {

           struct binder_txn *txn = (void*) ptr;

           if ((end - ptr) *sizeof(uint32_t) < sizeof(struct binder_txn)) {

                ALOGE("parse: reply toosmall!\n");

                return -1;

           }

           binder_dump_txn(txn);

           if (bio) {

                bio_init_from_txn(bio, txn);

                bio = 0;

           } else {

                    /* todo FREE BUFFER */

           }

           ptr += (sizeof(*txn) / sizeof(uint32_t));

           r = 0;

           break;

       }

       case BR_DEAD_BINDER: {

           struct binder_death *death = (void*) *ptr++;

           death->func(bs, death->ptr);

           break;

       }

       case BR_FAILED_REPLY:

           r = -1;

           break;

       case BR_DEAD_REPLY:

           r = -1;

           break;

       default:

           ALOGE("parse: OOPS %d\n", cmd);

           return -1;

       }

    }

 

   return r;

}

 

 

 

6.   svcmgr_handler ()

Frameworks/native/cmds/servicesmanager/Service_manager.c

int svcmgr_handler(struct binder_state *bs,

                   struct binder_txn *txn,

                   struct binder_io *msg,

                   struct binder_io *reply)

{

   struct svcinfo *si;

   uint16_t *s;

   unsigned len;

   void *ptr;

   uint32_t strict_policy;

   int allow_isolated;

 

//   ALOGI("target=%p code=%d pid=%d uid=%d\n",

//        txn->target, txn->code, txn->sender_pid, txn->sender_euid);

 

   if (txn->target != svcmgr_handle)

       return -1;

 

   // Equivalent to Parcel::enforceInterface(), reading the RPC

   // header with the strict mode policy mask and the interface name.

   // Note that we ignore the strict_policy and don't propagate it

   // further (since we do no outbound RPCs anyway).

   strict_policy = bio_get_uint32(msg);

    s= bio_get_string16(msg, &len);

   if ((len != (sizeof(svcmgr_id) / 2)) ||

       memcmp(svcmgr_id, s, sizeof(svcmgr_id))) {

       fprintf(stderr,"invalid id %s\n", str8(s));

       return -1;

    }

 

   switch(txn->code) {

   case SVC_MGR_GET_SERVICE:

   case SVC_MGR_CHECK_SERVICE:

       s = bio_get_string16(msg, &len);

       ptr = do_find_service(bs, s, len, txn->sender_euid);

       if (!ptr)

           break;

       bio_put_ref(reply, ptr);

       return 0;

 

   case SVC_MGR_ADD_SERVICE:

       s = bio_get_string16(msg, &len);

       ptr = bio_get_ref(msg);

       allow_isolated = bio_get_uint32(msg) ? 1 : 0;

       if (do_add_service(bs, s, len, ptr,txn->sender_euid, allow_isolated))

           return -1;

       break;

 

   case SVC_MGR_LIST_SERVICES: {

       unsigned n = bio_get_uint32(msg);

 

       si = svclist;

       while ((n-- > 0) && si)

           si = si->next;

       if (si) {

           bio_put_string16(reply, si->name);

           return 0;

       }

       return -1;

    }

   default:

       ALOGE("unknown code %d\n", txn->code);

       return -1;

    }

 

   bio_put_uint32(reply, 0);

   return 0;

}

 

 

 

 

 

 

 

 

 

 

 

In executeCommand function

 

               sp<BBinder> b((BBinder*)tr.cookie);

               conststatus_t error = b->transact(tr.code, buffer, &reply, tr.flags);

 

here, b can be CameraService  / MediaPlayerService etc

MediaPlayerService inherits from BnMediaPlayerService which fromBnInterface,  which from BBinder

BnMediaPlayerService rewrite onTransact ofBBinder,  neither rewrite transact

Therefore, here BBinder::transact() called.

 

1.      b->transact()

2.      BBinder::transact()

Frameworks/native/libs/binder/Binder.cpp

status_tBBinder::transact(

    uint32_t code, const Parcel& data,Parcel* reply, uint32_t flags)

{

    data.setDataPosition(0);

 

    status_t err = NO_ERROR;

    switch (code) {

        case PING_TRANSACTION:

            reply->writeInt32(pingBinder());

            break;

        default:

           err =onTransact(code, data, reply, flags);

            break;

    }

 

    if(reply != NULL) {

        reply->setDataPosition(0);

    }

 

    return err;

}

3.      BnMediaPlayerService::onTransact()

Frameworks/av/media/libmedia/IMediaPlayerService.cpp

status_t BnMediaPlayerService::onTransact(

   uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)

{

   switch (code) {

       case CREATE: {

           CHECK_INTERFACE(IMediaPlayerService, data, reply);

           sp<IMediaPlayerClient> client =

               interface_cast<IMediaPlayerClient>(data.readStrongBinder());

           int audioSessionId = data.readInt32();

           sp<IMediaPlayer> player = create(client, audioSessionId);

           reply->writeStrongBinder(player->asBinder());

           return NO_ERROR;

       } break;

       case DECODE_URL: {

           CHECK_INTERFACE(IMediaPlayerService, data, reply);

           const char* url = data.readCString();

           uint32_t sampleRate;

           int numChannels;

           audio_format_t format;

           sp<IMemory> player = decode(url, &sampleRate,&numChannels, &format);

           reply->writeInt32(sampleRate);

           reply->writeInt32(numChannels);

           reply->writeInt32((int32_t) format);

           reply->writeStrongBinder(player->asBinder());

           return NO_ERROR;

       } break;

       case DECODE_FD: {

           CHECK_INTERFACE(IMediaPlayerService, data, reply);

           int fd = dup(data.readFileDescriptor());

           int64_t offset = data.readInt64();

           int64_t length = data.readInt64();

           uint32_t sampleRate;

           int numChannels;

           audio_format_t format;

           sp<IMemory> player = decode(fd, offset, length, &sampleRate,&numChannels, &format);

           reply->writeInt32(sampleRate);

           reply->writeInt32(numChannels);

           reply->writeInt32((int32_t) format);

           reply->writeStrongBinder(player->asBinder());

           return NO_ERROR;

       } break;

       case CREATE_MEDIA_RECORDER: {

           CHECK_INTERFACE(IMediaPlayerService, data, reply);

           sp<IMediaRecorder> recorder = createMediaRecorder();

           reply->writeStrongBinder(recorder->asBinder());

           return NO_ERROR;

       } break;

       case CREATE_METADATA_RETRIEVER: {

           CHECK_INTERFACE(IMediaPlayerService, data, reply);

            sp<IMediaMetadataRetriever>retriever = createMetadataRetriever();

           reply->writeStrongBinder(retriever->asBinder());

           return NO_ERROR;

       } break;

       case GET_OMX: {

           CHECK_INTERFACE(IMediaPlayerService, data, reply);

           sp<IOMX> omx = getOMX();

           reply->writeStrongBinder(omx->asBinder());

           return NO_ERROR;

       } break;

       case MAKE_CRYPTO: {

           CHECK_INTERFACE(IMediaPlayerService, data, reply);

           sp<ICrypto> crypto = makeCrypto();

           reply->writeStrongBinder(crypto->asBinder());

           return NO_ERROR;

       } break;

       case MAKE_DRM: {

           CHECK_INTERFACE(IMediaPlayerService, data, reply);

           sp<IDrm> drm = makeDrm();

           reply->writeStrongBinder(drm->asBinder());

           return NO_ERROR;

       } break;

       case MAKE_HDCP: {

           CHECK_INTERFACE(IMediaPlayerService, data, reply);

           bool createEncryptionModule = data.readInt32();

           sp<IHDCP> hdcp = makeHDCP(createEncryptionModule);

           reply->writeStrongBinder(hdcp->asBinder());

           return NO_ERROR;

       } break;

       case ADD_BATTERY_DATA: {

           CHECK_INTERFACE(IMediaPlayerService, data, reply);

           uint32_t params = data.readInt32();

           addBatteryData(params);

           return NO_ERROR;

       } break;

       case PULL_BATTERY_DATA: {

           CHECK_INTERFACE(IMediaPlayerService, data, reply);

           pullBatteryData(reply);

           return NO_ERROR;

       } break;

       case LISTEN_FOR_REMOTE_DISPLAY: {

           CHECK_INTERFACE(IMediaPlayerService, data, reply);

           sp<IRemoteDisplayClient> client(

                    interface_cast<IRemoteDisplayClient>(data.readStrongBinder()));

           String8 iface(data.readString8());

           sp<IRemoteDisplay> display(listenForRemoteDisplay(client, iface));

           reply->writeStrongBinder(display->asBinder());

           return NO_ERROR;

       } break;

       case UPDATE_PROXY_CONFIG:

       {

           CHECK_INTERFACE(IMediaPlayerService, data, reply);

 

           const char *host = NULL;

           int32_t port = 0;

           const char *exclusionList = NULL;

 

           if (data.readInt32()) {

                host = data.readCString();

                port = data.readInt32();

                exclusionList =data.readCString();

           }

 

           reply->writeInt32(updateProxyConfig(host, port, exclusionList));

 

           return OK;

       }

       default:

           return BBinder::onTransact(code, data, reply, flags);

    }

}

 

 

你可能感兴趣的:(Android Media Service Binder Machine)