ServiceManager 是怎么获取的
1. Java 入口
ServiceManager.getService(name) 先查本进程缓存,没命中就走 rawGetService(name):
//ServiceManager.java
public static IBinder getService(String name) {
try {
IBinder service = sCache.get(name);
if (service != null) {
return service;
} else {
return Binder.allowBlocking(rawGetService(name));
}
rawGetService 实际调的是:
//ServiceManager.java
private static IBinder rawGetService(String name) throws RemoteException {
final long start = sStatLogger.getTime();
final IBinder binder =
getIServiceManager().getService2(name).getServiceWithMetadata().service;
2. getIServiceManager() 怎么拿到 servicemanager
第一次会调用:
//ServiceManager.java
private static IServiceManager getIServiceManager() {
if (sServiceManager != null) {
return sServiceManager;
}
// Find the service manager
sServiceManager = ServiceManagerNative
.asInterface(Binder.allowBlocking(BinderInternal.getContextObject()));
return sServiceManager;
}
关键是 BinderInternal.getContextObject()。它进 JNI 后:
// android_util_binder.cpp
static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
{
sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
return javaObjectForIBinder(env, b);
}
Native 里 getContextObject() 固定拿 handle 0:
// ProcessState.cpp
sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
{
sp<IBinder> context = getStrongProxyForHandle(0);
if (context) {
// The root object is special since we get it directly from the driver, it is never
// written by Parcell::writeStrongBinder.
internal::Stability::markCompilationUnit(context.get());
}
handle 0 是 Binder 驱动约定的 context manager,也就是 servicemanager。
3. BpBinder 在哪里出现
getStrongProxyForHandle(0) 如果本进程还没有 handle 0 的代理,就创建一个 BpBinder:
// ProcessState.cpp
Parcel data;
status_t status = ipc->transact(
0, IBinder::PING_TRANSACTION, data, nullptr, 0);
// ...
sp<BpBinder> b = BpBinder::PrivateAccessor::create(handle, &postTask);
你当前看到的这行就是创建远端 Binder 代理:
// ProcessState.cpp
return sp<BpBinder>::make(BinderHandle{handle}, trackedUid);
所以 client 进程里拿到的 servicemanager 不是 servicemanager 对象本体,而是:
Java BinderProxy -> native BinderProxyNativeData.mObject -> sp<BpBinder(handle=0)>
JNI 包装点在这里:
//android_util_Binder.cpp
return javaObjectForIBinder(env, b);
//...
jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val{
if (val == NULL) return NULL;
if (val->checkSubclass(&gBinderOffsets)) {
// It's a JavaBBinder created by ibinderForJavaObject. Already has Java object.
jobject object = static_cast<JavaBBinder*>(val.get())->object();
LOG_DEATH_FREEZE("objectForBinder %p: it's our own %p!\n", val.get(), object);
return object;
}
BinderProxyNativeData* nativeData = new BinderProxyNativeData();
nativeData->mOrgue = sp<DeathRecipientList>::make();
nativeData->mFrozenStateChangeCallbackList = sp<FrozenStateChangeCallbackList>::make();
nativeData->mObject = val;
jobject object = env->CallStaticObjectMethod(gBinderProxyOffsets.mClass,
gBinderProxyOffsets.mGetInstance, (jlong) nativeData, (jlong) val.get());
我们再看看这个gBinderProxyOffsets,具体是个什么,这个得到了一个什么样的java对象,谜底就快解开了
//android_util_Binder.cpp
static struct binderproxy_offsets_t
{
// Class state.
jclass mClass;
jmethodID mGetInstance;
jmethodID mSendDeathNotice;
jmethodID mInvokeFrozenStateChangeCallback;
// Object state.
jfieldID mNativeData; // Field holds native pointer to BinderProxyNativeData.
} gBinderProxyOffsets;
const char* const kBinderProxyPathName = "android/os/BinderProxy";
static int int_register_android_os_BinderProxy(JNIEnv* env)
{
jclass clazz = FindClassOrDie(env, kBinderProxyPathName);
gBinderProxyOffsets.mClass = MakeGlobalRefOrDie(env, clazz);
gBinderProxyOffsets.mGetInstance = GetStaticMethodIDOrDie(env, clazz, "getInstance",
"(JJ)Landroid/os/BinderProxy;");
gBinderProxyOffsets.mSendDeathNotice =
GetStaticMethodIDOrDie(env, clazz, "sendDeathNotice",
"(Landroid/os/IBinder$DeathRecipient;Landroid/os/IBinder;)V");
gBinderProxyOffsets.mInvokeFrozenStateChangeCallback =
GetStaticMethodIDOrDie(env, clazz, "invokeFrozenStateChangeCallback",
"(Landroid/os/IBinder$FrozenStateChangeCallback;Landroid/os/"
"IBinder;I)V");
gBinderProxyOffsets.mNativeData = GetFieldIDOrDie(env, clazz, "mNativeData", "J");
}
原来这个gBinderProxyOffsets 中保存的就是Java 中BinderProxy。
4. Client 怎么“连到” servicemanager
Client 打开 /dev/binder,然后向 handle 0 发 transaction。
BpBinder::transact():
// BpBinder.cpp
status_t BpBinder::transact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
// ...
status = IPCThreadState::self()->transact(binderHandle(), code, data, reply, flags);
IPCThreadState::transact() 把目标 handle、code、Parcel 写成 BC_TRANSACTION:
// IPCThreadState.cpp
status_t IPCThreadState::transact(int32_t handle,
uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags)
{
// ...
err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, nullptr);
...
真正进驱动是这里:
#if defined(BINDER_WITH_KERNEL_IPC)
if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)
err = NO_ERROR;
else
err = -errno;
驱动看到 target handle 是 0,就把请求投递给注册为 context manager 的 servicemanager 进程。
下篇文章我们再看看 servicemanager 是如何接收数据并返回的。