Binder学習のaddService

8563 ワード

次のページ:http://blog.csdn.net/cs_lht/articale/detail/8160968
MediaPlayer ServiceがどのようにServiceManagerに追加されているかを確認します。
コードパス:frame ework/base/media/libmediappervice/MediaPlayer Service.cpp
void MediaPlayerService::instantiate() {
    defaultServiceManager()->addService(
            String16("media.player"), new MediaPlayerService());
}
default ServiceManagerはどうやって来たのですか?前の記事で説明しましたが、帰ってきたのはBpServiceMangerですよね?
私たちはBpServiceManagerのaddServiceがどのように働いているかを見ます。メディアPlayer ServiceをServiceManagerにどうやって追加しますか?
ServiceManagerはここで特別に説明します。BnServiceManagerを引き継ぐのではなく、ServiceManagerという実行可能なプログラムによって代替されます。
フレームワーク/base/cmds/servicemanager/service_manager.
    virtual status_t addService(const String16& name, const sp<IBinder>& service)
    {
        Parcel data, reply;
        data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());//android.so.IServicemanger
        data.writeString16(name);
        data.writeStrongBinder(service);
        status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);
        return err == NO_ERROR ? reply.readInt32() : err;
    }
のこのコードの核心コードは、remote->transactです。前の勉強を通して、コードはどこで見られますか?間違いないです。frame eborks/base/libs/binder/BpBinder.cppです。
status_t BpBinder::transact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
    // Once a binder has died, it will never come 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;
}
は次いでIPCThreadStateを見る。
IPCThreadState* IPCThreadState::self()
{
    if (gHaveTLS) {
restart:
        const pthread_key_t k = gTLS;
        IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k);
        if (st) return st;
        return new IPCThreadState;
    }
//        
}
pthread_get specificはスレッド空間から格納されたオブジェクトを取得し、空に戻るとIPCThreadStateオブジェクトを作成する。
PICThreadStateの構造関数を見てみましょう。
IPCThreadState::IPCThreadState()
    : mProcess(ProcessState::self()), mMyThreadId(androidGetTid())
{
    pthread_setspecific(gTLS, this);
    clearCaller();
    mIn.setDataCapacity(256);
    mOut.setDataCapacity(256);
}
このコンストラクタは、スレッド空間に自分を加えたもので、スレッド内のオブジェクト共有のために、mInはBinder駆動からデータを受信し、mOutはBinder駆動に送信されたデータを記憶するために使用される。
はい、私達はもう一回トランジットを見に来ます。
status_t IPCThreadState::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 from pid %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 (reply) {
            err = waitForResponse(reply);
        } else {
            Parcel fakeReply;
            err = waitForResponse(&fakeReply);
        }
        
        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 << "(none requested)" << endl;
        }
    } else {
        err = waitForResponse(NULL, NULL);
    }
    
    return err;
}
writeTransation DataはBinderドライバに送るデータをmOutに書いています。またBC(u)に注意してください。TRANSACTIONは、Binder駆動によって直接実行される。
次にウォitForResonseを見てみます。これは関数からBinderからのフィードバックを待っていることが分かります。
status_t IPCThreadState::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 << "Processing waitForResponse 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:
            {
                LOG_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));
                LOG_ASSERT(err == NO_ERROR, "Not enough command data for brREPLY");
                if (err != NO_ERROR) goto finish;

                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<const size_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;
        }
    }
この関数のコードは全部貼り付けられていますが、内容が重要です。
最初の関数はBinderへの道を発見したと感じるかもしれません。talkWithDriver()
if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)
これは本当にBinderドライバとコミュニケーションするところです。bwrに注意してください。Binderと専門的にコミュニケーションする構造体binder_です。write_read
struct binder_write_read {
    signed long write_size;
    signed long write_consumed;
    unsigned long write_buffer;
    signed long read_size;
    signed long read_consumed;
    unsigned long read_buffer;
};
には、writeとread部分の変数が含まれていますので、Binderにデータを送るためにも、Binderに返却されたデータを伝えるためにも使えます。
Driverがどのようにこのコマンドを処理しているかについては、別のブログで分析します。
だからtalkWithDriverの最後にbwrの中のBinderの帰るデータをまたmIn変数の中に書き込んで、それからwaitForResonsに帰ります。
ここでまず推測してみます。もしドラヴィーが戻ってきたら、マンドはBR_です。TRANSACTION_COMPLETEは、addService ServiceManagerのカスタマーサービスのエンドコードを分析しました。
次に、私達はDriverがどのようにServiceManagerを見つけられたかを分析します。ServiceManagerはどのようにDrvierの召喚を待っていますか?これらのServerの対象をどのように保存しますか?DriverはまたServiceManagerのクライアントに戻ります。