コアサービス開発に必要な情報を整理2
onTransact()(IBinder.transact())を直接扱う実装が必要で煩雑になるところを、Proxy-Stubパターンでより簡単に扱える。というC++とJavaの実装例をまとめるのがこのテーマのゴール。で、これは自分用のメモメモ。
chiaki@ubuntu:~/mydroid/frameworks/base/libs/binder$ view ProcessState.cpp sp<ProcessState> ProcessState::self() { if (gProcess != NULL) return gProcess; AutoMutex _l(gProcessMutex); if (gProcess == NULL) gProcess = new ProcessState; return gProcess; } void ProcessState::startThreadPool() { AutoMutex _l(mLock); if (!mThreadPoolStarted) { mThreadPoolStarted = true; spawnPooledThread(true); } } void ProcessState::spawnPooledThread(bool isMain) { if (mThreadPoolStarted) { int32_t s = android_atomic_add(1, &mThreadPoolSeq); char buf[32]; sprintf(buf, "Binder Thread #%d", s); LOGV("Spawning new pooled thread, name=%s\n", buf); sp<Thread> t = new PoolThread(isMain); t->run(buf); } }
chiaki@ubuntu:~/mydroid/frameworks/base/libs/binder$ vi IPCThreadState.cpp void IPCThreadState::joinThreadPool(bool isMain) { } status_t IPCThreadState::transact(int32_t handle, uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { } status_t IPCThreadState::talkWithDriver(bool doReceive) { } status_t IPCThreadState::executeCommand(int32_t cmd) { …略 case BR_TRANSACTION: { …略 if (tr.target.ptr) { sp<BBinder> b((BBinder*)tr.cookie); const status_t error = b->transact(tr.code, buffer, &reply, tr.flags); …略 } } }
chiaki@ubuntu:~/mydroid/frameworks$ vi base/core/jni/android_util_Binder.cpp virtual status_t onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0) { …略 jboolean res = env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact, code, (int32_t)&data, (int32_t)reply, flags); chiaki@ubuntu:~/mydroid/frameworks$ vi base/core/java/android/os/Binder.java private boolean execTransact(int code, int dataObj, int replyObj, int flags) { …略 try { res = onTransact(code, data, reply, flags); } catch (RemoteException e) { …略
のあたり。
ProcessState::self()->startThreadPool(); IPCThreadState::self()->joinThreadPool();