Binder学習のaddService
8563 ワード
次のページ:http://blog.csdn.net/cs_lht/articale/detail/8160968
MediaPlayer ServiceがどのようにServiceManagerに追加されているかを確認します。
コードパス:frame ework/base/media/libmediappervice/MediaPlayer Service.cpp
私たちはBpServiceManagerのaddServiceがどのように働いているかを見ます。メディアPlayer ServiceをServiceManagerにどうやって追加しますか?
ServiceManagerはここで特別に説明します。BnServiceManagerを引き継ぐのではなく、ServiceManagerという実行可能なプログラムによって代替されます。
フレームワーク/base/cmds/servicemanager/service_manager.
PICThreadStateの構造関数を見てみましょう。
はい、私達はもう一回トランジットを見に来ます。
次にウォitForResonseを見てみます。これは関数からBinderからのフィードバックを待っていることが分かります。
最初の関数はBinderへの道を発見したと感じるかもしれません。talkWithDriver()
Driverがどのようにこのコマンドを処理しているかについては、別のブログで分析します。
だからtalkWithDriverの最後にbwrの中のBinderの帰るデータをまたmIn変数の中に書き込んで、それからwaitForResonsに帰ります。
ここでまず推測してみます。もしドラヴィーが戻ってきたら、マンドはBR_です。TRANSACTION_COMPLETEは、addService ServiceManagerのカスタマーサービスのエンドコードを分析しました。
次に、私達はDriverがどのようにServiceManagerを見つけられたかを分析します。ServiceManagerはどのようにDrvierの召喚を待っていますか?これらのServerの対象をどのように保存しますか?DriverはまたServiceManagerのクライアントに戻ります。
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_readstruct 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のクライアントに戻ります。