当前位置:网站首页>(O)ServiceManager分析(一)之BinderInternal.getContextObject
(O)ServiceManager分析(一)之BinderInternal.getContextObject
2020-11-08 16:12:00 【天王盖地虎626】
1. Binder, JNI函数的注册
在分析BinderInternal的getContextObject函数之前,我们有必要先看一下Binder中JNI函数的注册情况
android_os_Binder.cpp
int register_android_os_Binder(JNIEnv* env)
{
// Leo, 注册Binder的相关JNI函数
if (int_register_android_os_Binder(env) < 0)
return -1;
// Leo, 注册Binderinternal的相关JNI函数
if (int_register_android_os_BinderInternal(env) < 0)
return -1;
// Leo, 注册BinderProxy的相关JNI函数
if (int_register_android_os_BinderProxy(env) < 0)
return -1;
jclass clazz = FindClassOrDie(env, "android/util/Log");
gLogOffsets.mClass = MakeGlobalRefOrDie(env, clazz);
gLogOffsets.mLogE = GetStaticMethodIDOrDie(env, clazz, "e",
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Throwable;)I");
clazz = FindClassOrDie(env, "android/os/ParcelFileDescriptor");
gParcelFileDescriptorOffsets.mClass = MakeGlobalRefOrDie(env, clazz);
gParcelFileDescriptorOffsets.mConstructor = GetMethodIDOrDie(env, clazz, "<init>",
"(Ljava/io/FileDescriptor;)V");
clazz = FindClassOrDie(env, "android/os/StrictMode");
gStrictModeCallbackOffsets.mClass = MakeGlobalRefOrDie(env, clazz);
gStrictModeCallbackOffsets.mCallback = GetStaticMethodIDOrDie(env, clazz,
"onBinderStrictModePolicyChange", "(I)V");
return 0;
}
至于为什么会开始走到这个方法,我们在此不讨论
这个方法,主要是,调用了各个register方法,注册了一些JNI函数,那么具体怎么注册的,我们进入方法中查看,先看int_register_android_os_Binder
static const JNINativeMethod gBinderMethods[] = {
/* name, signature, funcPtr */
{ "getCallingPid", "()I", (void*)android_os_Binder_getCallingPid },
{ "getCallingUid", "()I", (void*)android_os_Binder_getCallingUid },
{ "clearCallingIdentity", "()J", (void*)android_os_Binder_clearCallingIdentity },
{ "restoreCallingIdentity", "(J)V", (void*)android_os_Binder_restoreCallingIdentity },
{ "setThreadStrictModePolicy", "(I)V", (void*)android_os_Binder_setThreadStrictModePolicy },
{ "getThreadStrictModePolicy", "()I", (void*)android_os_Binder_getThreadStrictModePolicy },
{ "flushPendingCommands", "()V", (void*)android_os_Binder_flushPendingCommands },
{ "init", "()V", (void*)android_os_Binder_init },
{ "destroy", "()V", (void*)android_os_Binder_destroy },
{ "blockUntilThreadAvailable", "()V", (void*)android_os_Binder_blockUntilThreadAvailable }
};
const char* const kBinderPathName = "android/os/Binder";
static int int_register_android_os_Binder(JNIEnv* env)
{
jclass clazz = FindClassOrDie(env, kBinderPathName);
gBinderOffsets.mClass = MakeGlobalRefOrDie(env, clazz);
gBinderOffsets.mExecTransact = GetMethodIDOrDie(env, clazz, "execTransact", "(IJJI)Z");
gBinderOffsets.mObject = GetFieldIDOrDie(env, clazz, "mObject", "J");
return RegisterMethodsOrDie(
env, kBinderPathName,
gBinderMethods, NELEM(gBinderMethods));
}
static struct bindernative_offsets_t
{
// Class state.
jclass mClass;
jmethodID mExecTransact;
// Object state.
jfieldID mObject;
} gBinderOffsets;
那么,从这个方法,我们可以看到,将gBinderOffsets和Java世界android.os.Binder类,进行关联,并且指定
gBinderOffsets.mClass为android.os.Binder类
gBinderOffsets.mExecTransact为android.os.Binder.execTransact方法
gBinderOffsets.mObject对应为android.os.Binder的mObject对象所对应的值
并且,将gBinderMethods中所对应的Java世界的方法和C世界的相对应的方法一一对应
那么上述的其他两个方法,所达到的目的也是和上述方法一致,我们可以得出如下的其他结论
1). BinderInternal
static const JNINativeMethod gBinderInternalMethods[] = {
/* name, signature, funcPtr */
// Leo, 将android_os_BinderInternal_getContextObject方法和com.android.internal.os.BinderInternal.getContextObject方法进行绑定
{ "getContextObject", "()Landroid/os/IBinder;", (void*)android_os_BinderInternal_getContextObject },
// Leo, 将android_os_BinderInternal_joinThreadPool方法和com.android.internal.os.BinderInternal.joinThreadPool方法进行绑定
{ "joinThreadPool", "()V", (void*)android_os_BinderInternal_joinThreadPool },
// Leo, 将android_os_BinderInternal_disableBackgroundScheduling方法和com.android.internal.os.BinderInternal.disableBackgroundScheduling方法进行绑定
{ "disableBackgroundScheduling", "(Z)V", (void*)android_os_BinderInternal_disableBackgroundScheduling },
// Leo, 将android_os_BinderInternal_setMaxThreads方法和com.android.internal.os.BinderInternal.setMaxThreads方法进行绑定
{ "setMaxThreads", "(I)V", (void*)android_os_BinderInternal_setMaxThreads },
// Leo, 将android_os_BinderInternal_handleGc方法和com.android.internal.os.BinderInternal.handleGc方法进行绑定
{ "handleGc", "()V", (void*)android_os_BinderInternal_handleGc }
};
const char* const kBinderInternalPathName = "com/android/internal/os/BinderInternal";
static int int_register_android_os_BinderInternal(JNIEnv* env)
{
jclass clazz = FindClassOrDie(env, kBinderInternalPathName);
// Leo, gBinderInternalOffsets.mClass赋值为BinderInternal.java文件
gBinderInternalOffsets.mClass = MakeGlobalRefOrDie(env, clazz);
gBinderInternalOffsets.mForceGc = GetStaticMethodIDOrDie(env, clazz, "forceBinderGc", "()V");
// Leo, 注册JNI函数
return RegisterMethodsOrDie(
env, kBinderInternalPathName,
gBinderInternalMethods, NELEM(gBinderInternalMethods));
}
static struct binderinternal_offsets_t
{
// Class state.
jclass mClass;
jmethodID mForceGc;
} gBinderInternalOffsets;
gBinderInternalOffsets.mClass和Java世界的com.android.internal.os.BinderInternal类对应
gBinderInternalOffsets.mForceGc和com.android.internal.os.BinderInternal类中的forceBinderGc方法对应
并且将gBinderInternalMethods所对应的Java世界的方法和C世界对应方法一一对应
2). BinderProxy
static const JNINativeMethod gBinderProxyMethods[] = {
/* name, signature, funcPtr */
{"pingBinder", "()Z", (void*)android_os_BinderProxy_pingBinder},
{"isBinderAlive", "()Z", (void*)android_os_BinderProxy_isBinderAlive},
{"getInterfaceDescriptor", "()Ljava/lang/String;", (void*)android_os_BinderProxy_getInterfaceDescriptor},
{"transactNative", "(ILandroid/os/Parcel;Landroid/os/Parcel;I)Z", (void*)android_os_BinderProxy_transact},
{"linkToDeath", "(Landroid/os/IBinder$DeathRecipient;I)V", (void*)android_os_BinderProxy_linkToDeath},
{"unlinkToDeath", "(Landroid/os/IBinder$DeathRecipient;I)Z", (void*)android_os_BinderProxy_unlinkToDeath},
{"destroy", "()V", (void*)android_os_BinderProxy_destroy},
};
const char* const kBinderProxyPathName = "android/os/BinderProxy";
static int int_register_android_os_BinderProxy(JNIEnv* env)
{
jclass clazz = FindClassOrDie(env, "java/lang/Error");
gErrorOffsets.mClass = MakeGlobalRefOrDie(env, clazz);
clazz = FindClassOrDie(env, kBinderProxyPathName);
gBinderProxyOffsets.mClass = MakeGlobalRefOrDie(env, clazz);
gBinderProxyOffsets.mConstructor = GetMethodIDOrDie(env, clazz, "<init>", "()V");
gBinderProxyOffsets.mSendDeathNotice = GetStaticMethodIDOrDie(env, clazz, "sendDeathNotice",
"(Landroid/os/IBinder$DeathRecipient;)V");
gBinderProxyOffsets.mObject = GetFieldIDOrDie(env, clazz, "mObject", "J");
gBinderProxyOffsets.mSelf = GetFieldIDOrDie(env, clazz, "mSelf",
"Ljava/lang/ref/WeakReference;");
gBinderProxyOffsets.mOrgue = GetFieldIDOrDie(env, clazz, "mOrgue", "J");
clazz = FindClassOrDie(env, "java/lang/Class");
gClassOffsets.mGetName = GetMethodIDOrDie(env, clazz, "getName", "()Ljava/lang/String;");
return RegisterMethodsOrDie(
env, kBinderProxyPathName,
gBinderProxyMethods, NELEM(gBinderProxyMethods));
}
static struct binderproxy_offsets_t
{
// Class state.
jclass mClass;
jmethodID mConstructor;
jmethodID mSendDeathNotice;
// Object state.
jfieldID mObject;
jfieldID mSelf;
jfieldID mOrgue;
} gBinderProxyOffsets;
gBinderProxyOffsets.mClass和Java世界的android.os.BinderProxy类对应
gBinderProxyOffsets.mConstructor和android.os.BinderProxy类中的init方法对应
gBinderProxyOffsets.mSendDeathNotice和android.os.BinderProxy类中的sendDeathNotice方法对应
gBinderProxyOffsets.mSelf和android.os.BinderProxy类中的mSelf对象对应
gBinderProxyOffsets.mObject和android.os.BinderProxy类中的mObject对象对应
并且将gBinderProxyMethods所对应的Java世界的方法和C世界对应方法一一对应
2. BinderInternal.getContextObject函数分析
BinderInternal.java
/**
* Return the global "context object" of the system. This is usually
* an implementation of IServiceManager, which you can use to find
* other services.
*/
public static final native IBinder getContextObject();
调用的是native层的getContextObject方法,还记得此前的Binder的JNI注册中,注册的BinderInternal方法么?
static const JNINativeMethod gBinderInternalMethods[] = {
/* name, signature, funcPtr */
// Leo, 将android_os_BinderInternal_getContextObject方法和com.android.internal.os.BinderInternal.getContextObject方法进行绑定
{ "getContextObject", "()Landroid/os/IBinder;", (void*)android_os_BinderInternal_getContextObject },
// Leo, 将android_os_BinderInternal_joinThreadPool方法和com.android.internal.os.BinderInternal.joinThreadPool方法进行绑定
{ "joinThreadPool", "()V", (void*)android_os_BinderInternal_joinThreadPool },
// Leo, 将android_os_BinderInternal_disableBackgroundScheduling方法和com.android.internal.os.BinderInternal.disableBackgroundScheduling方法进行绑定
{ "disableBackgroundScheduling", "(Z)V", (void*)android_os_BinderInternal_disableBackgroundScheduling },
// Leo, 将android_os_BinderInternal_setMaxThreads方法和com.android.internal.os.BinderInternal.setMaxThreads方法进行绑定
{ "setMaxThreads", "(I)V", (void*)android_os_BinderInternal_setMaxThreads },
// Leo, 将android_os_BinderInternal_handleGc方法和com.android.internal.os.BinderInternal.handleGc方法进行绑定
{ "handleGc", "()V", (void*)android_os_BinderInternal_handleGc }
};
getContextObject和android_util_Binder.cpp文件中的android_os_BinderInternal_getContextObject方法对应
static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
{
// Leo, 返回的是new BpBinder(0)
sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
// Leo, 这个方法是JNI的应用,返回的是BinderProxy
return javaObjectForIBinder(env, b);
}
此处主要是调用了两个方法,那么我们一个个地来看
3. ProcessState的getContextObject方法
ProcessState.cpp
sp<ProcessState> ProcessState::self()
{
Mutex::Autolock _l(gProcessMutex);
if (gProcess != NULL) {
return gProcess;
}
// Leo, 初始化ProcessState对象
gProcess = new ProcessState;
return gProcess;
}
OK,单例模式,初始化ProcessState
ProcessState::ProcessState()
: mDriverFD(open_driver()) // Leo, 打开binder设备
, mVMStart(MAP_FAILED)
, mThreadCountLock(PTHREAD_MUTEX_INITIALIZER)
, mThreadCountDecrement(PTHREAD_COND_INITIALIZER)
, mExecutingThreadsCount(0)
, mMaxThreads(DEFAULT_MAX_BINDER_THREADS)
, mStarvationStartTimeMs(0)
, mManagesContexts(false)
, mBinderContextCheckFunc(NULL)
, mBinderContextUserData(NULL)
, mThreadPoolStarted(false)
, mThreadPoolSeq(1)
{
if (mDriverFD >= 0) {
// mmap the binder, providing a chunk of virtual address space to receive transactions.
// Leo, 为binder设备分配地址空间
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;
}
}
LOG_ALWAYS_FATAL_IF(mDriverFD < 0, "Binder driver could not be opened. Terminating.");
}
ProcessState的初始化中,打开了/dev/binder设备,并且为该设备分配地址空间
接下来,调用了其getContextObject方法
sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
{
return getStrongProxyForHandle(0);
}
再接下来
sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{
sp<IBinder> result;
AutoMutex _l(mLock);
handle_entry* e = lookupHandleLocked(handle);
if (e != NULL) {
......
IBinder* b = e->binder;
if (b == NULL || !e->refs->attemptIncWeak(this)) {
if (handle == 0) {
......
Parcel data;
status_t status = IPCThreadState::self()->transact(
0, IBinder::PING_TRANSACTION, data, NULL, 0);
if (status == DEAD_OBJECT)
return NULL;
}
b = new BpBinder(handle);
e->binder = b;
if (b) e->refs = b->getWeakRefs();
result = b;
} else {
// This little bit of nastyness is to allow us to add a primary
// reference to the remote proxy when this team doesn't have one
// but another team is sending the handle to us.
result.force_set(b);
e->refs->decWeak(this);
}
}
return result;
}
ProcessState::handle_entry* ProcessState::lookupHandleLocked(int32_t handle)
{
const size_t N=mHandleToObject.size();
if (N <= (size_t)handle) {
handle_entry e;
e.binder = NULL;
e.refs = NULL;
status_t err = mHandleToObject.insertAt(e, N, handle+1-N);
if (err < NO_ERROR) return NULL;
}
return &mHandleToObject.editItemAt(handle);
}
从这儿看,先调用lookupHandleLocked方法,由于是第一次调用,因此新建一个handle_entry,并返回,而且其binder和refs为NULL
那么getStrongProxyForHandle方法接着往下走,由于binder为NULL,mHandle传入的是0,因此进入判断条件中,最后new BpBinder,且参数为0
因此,
sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
返回的是new BpBinder(0)
4. javaObjectForIBinder方法解析
// Leo, val 为 new BpBinder(0)
jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val)
{
// Leo, 不为NULL
if (val == NULL) return NULL;
/*
* Leo, 由于BpBinder没有继承Binder的checkSubclass方法
* 因此调用的是Binder.cpp中的checkSubclass方法,返回false
*/
if (val->checkSubclass(&gBinderOffsets)) {
// One of our own!
jobject object = static_cast<JavaBBinder*>(val.get())->object();
LOGDEATH("objectForBinder %p: it's our own %p!\n", val.get(), object);
return object;
}
// For the rest of the function we will hold this lock, to serialize
// looking/creation/destruction of Java proxies for native Binder proxies.
AutoMutex _l(mProxyLock);
// Someone else's... do we know about it?
// Leo, 第一次进来,显然是没有的
jobject object = (jobject)val->findObject(&gBinderProxyOffsets);
if (object != NULL) {
jobject res = jniGetReferent(env, object);
if (res != NULL) {
ALOGV("objectForBinder %p: found existing %p!\n", val.get(), res);
return res;
}
LOGDEATH("Proxy object %p of IBinder %p no longer in working set!!!", object, val.get());
android_atomic_dec(&gNumProxyRefs);
val->detachObject(&gBinderProxyOffsets);
env->DeleteGlobalRef(object);
}
// Leo, gBinderProxyOffsets.mClass = android/os/BinderProxy
object = env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor);
if (object != NULL) {
LOGDEATH("objectForBinder %p: created new proxy %p !\n", val.get(), object);
// The proxy holds a reference to the native object.
// Leo, gBinderProxyOffsets.mObject赋值为new BpBinder(0)
env->SetLongField(object, gBinderProxyOffsets.mObject, (jlong)val.get());
val->incStrong((void*)javaObjectForIBinder);
// The native object needs to hold a weak reference back to the
// proxy, so we can retrieve the same proxy if it is still active.
jobject refObject = env->NewGlobalRef(
env->GetObjectField(object, gBinderProxyOffsets.mSelf));
val->attachObject(&gBinderProxyOffsets, refObject,
jnienv_to_javavm(env), proxy_cleanup);
// Also remember the death recipients registered on this proxy
sp<DeathRecipientList> drl = new DeathRecipientList;
drl->incStrong((void*)javaObjectForIBinder);
env->SetLongField(object, gBinderProxyOffsets.mOrgue, reinterpret_cast<jlong>(drl.get()));
// Note that a new object reference has been created.
android_atomic_inc(&gNumProxyRefs);
incRefsCreated(env);
}
return object;
}
传入的参数,我们刚刚分析过了,第二个参数为new BpBinder(0),而BpBinder没有继承父类的checkSubclass方法,因此调用了其父类的该方法,返回false
而jobject object = (jobject)val->findObject(&gBinderProxyOffsets);第一次,显然为NULL,因此,接着往下
gBinderProxyOffsets.mClass,这个,此前我们有分析Binder的JNI注册,确认该值为android.os.BinderProxy
gBinderProxyOffsets.mConstructor,为其构造方法
因此,该语句返回的是Java层的对象BinderProxy
接下来,
env->SetLongField(object, gBinderProxyOffsets.mObject, (jlong)val.get());
将new BpBinder(0)赋值给gBinderProxyOffsets.mObject
至此,整个BinderInternal.getContextObject的流程,分析到此,就清晰了,初始化并返回的是BinderProxy对象,而且将BinderInternal的mObject对象赋值为new BpBinder(0)
版权声明
本文为[天王盖地虎626]所创,转载请带上原文链接,感谢
https://my.oschina.net/u/920274/blog/4706964
边栏推荐
- Suitable for C / C + + novice learning some projects, do not give me to miss!
- wanxin finance
- 关于update操作并发问题
- Flink: from introduction to Zhenxiang (3. Reading data from collection and file)
- 京东落地DevOps平台时爆发的冲突如何解决?
- Recurrence of Apache kylin Remote Code Execution Vulnerability (cve-2020-1956)
- 数据库连接报错之IO异常(The Network Adapter could not establish the connection)
- 阿里云加速增长,进一步巩固领先优势
- Workers, workers soul, draw lifelong members, become a person!
- Application of four ergodic square of binary tree
猜你喜欢
随机推荐
Travel notes of Suzhou
Golang ICMP Protocol detects viable hosts
What are the necessary laws and regulations to know when entering the Internet?
How does Alibaba cloud's maxcompute add (original ODPs) work?
我用 Python 找出了删除我微信的所有人并将他们自动化删除了
3、 The parameters of the function
Drink soda, a bottle of soda water 1 yuan, two empty bottles can change a bottle of soda, give 20 yuan, how much soda can you
Golang system ping program to detect the surviving host (any permission)
Solution of DEV-C + + unable to debug in Windows Environment
On the confirmation of original data assets
刚刚好,才是最理想的状态
Welcome to offer, grade P7, face-to-face sharing, 10000 words long text to take you through the interview process
Flink从入门到真香(10、Sink数据输出-Elasticsearch)
laravel8更新之速率限制改进
框架-SPI四种模式+通用设备驱动实现-源码
别再在finally里面释放资源了,解锁个新姿势!
Chapter 5 programming
谷歌开源能翻译101种语言的AI模型,只比Facebook多一种
浅谈,盘点历史上有哪些著名的电脑病毒,80%的人都不知道!
Is there no way out for older programmers?



