当前位置:网站首页>(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
边栏推荐
- VIM configuration tutorial + source code
- Solution of DEV-C + + unable to debug in Windows Environment
- 我用 Python 找出了删除我微信的所有人并将他们自动化删除了
- 大龄程序员没有出路吗?
- 这几个C++的坑,一旦踩中了,加班是肯定避免不了了!
- Solution to the problem of offline connection between ADB and mobile phone
- Is there no way out for older programmers?
- The first open source Chinese Bert pre training model in the financial field
- Alibaba cloud accelerates its growth and further consolidates its leading edge
- Eight ways to optimize if else code
猜你喜欢
打工人,打工魂,抽终身会员,成为人上人!
新型存算一体芯片诞生,利好人工智能应用~
Solution to the problem of offline connection between ADB and mobile phone
Apache Kylin远程代码执行漏洞复现(CVE-2020-1956)
Dev-c++在windows环境下无法debug(调试)的解决方案
Don't release resources in finally, unlock a new pose!
[Python 1-6] Python tutorial 1 -- number
软件开发中如何与人协作? | 每日趣闻
On the concurrency of update operation
阿里云视频云技术专家 LVS 演讲全文:《“云端一体”的智能媒体生产制作演进之路》
随机推荐
区块链周报:数字货币发展写入十四五规划;拜登邀请MIT数字货币计划高级顾问加入总统过渡团队;委内瑞拉推出国营加密交易所
RestfulApi 学习笔记——父子资源(四)
Improvement of maintenance mode of laravel8 update
框架-SPI四种模式+通用设备驱动实现-源码
Chapter 5 programming
AQS解析
The birth of a new integrated memory and computing chip is conducive to the application of artificial intelligence~
刚刚好,才是最理想的状态
[open source]. Net uses ORM to access Huawei gaussdb database
Ubuntu20.04 access FTP server garbled problem + upload files
Arduino IDE搭建ESP8266开发环境,文件下载过慢解决方法 | ESP-01制作WiFi开关教程,改造宿舍灯
【Python 1-6】Python教程之——数字
3、 The parameters of the function
我用 Python 找出了删除我微信的所有人并将他们自动化删除了
我们做了一个医疗版MNIST数据集,发现常见AutoML算法没那么好用
构建者模式(Builder pattern)
vim-配置教程+源码
Travel notes of Suzhou
浅谈OpenGL之DSA
Application of four ergodic square of binary tree