当前位置:网站首页>(O) Analysis of service manager (1) BinderInternal.getContextObject
(O) Analysis of service manager (1) BinderInternal.getContextObject
2020-11-08 16:12:00 【Tianwang gaidihu 626】
1. Binder, JNI Function registration
Based on the analysis of BinderInternal Of getContextObject Function before , Let's take a look first Binder in JNI Function registration
android_os_Binder.cpp
int register_android_os_Binder(JNIEnv* env)
{
// Leo, register Binder Correlation JNI function
if (int_register_android_os_Binder(env) < 0)
return -1;
// Leo, register Binderinternal Correlation JNI function
if (int_register_android_os_BinderInternal(env) < 0)
return -1;
// Leo, register BinderProxy Correlation JNI function
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;
}
As for why we started to go this way , We are not going to discuss
This method , Mainly , Called each of the register Method , Registered a few JNI function , So how to register , Let's go into the method and see , First look at 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;
that , From this method , We can see , take gBinderOffsets and Java The world android.os.Binder class , Association , And specify
gBinderOffsets.mClass by android.os.Binder class
gBinderOffsets.mExecTransact by android.os.Binder.execTransact Method
gBinderOffsets.mObject Corresponding to android.os.Binder Of mObject The value of the object
also , take gBinderMethods Corresponding to Java The way of the world and C The corresponding methods of the world correspond to each other
So the other two methods mentioned above , The goal achieved is also consistent with the above method , We can draw the following other conclusions
1). BinderInternal
static const JNINativeMethod gBinderInternalMethods[] = {
/* name, signature, funcPtr */
// Leo, take android_os_BinderInternal_getContextObject Methods and com.android.internal.os.BinderInternal.getContextObject Method to bind
{ "getContextObject", "()Landroid/os/IBinder;", (void*)android_os_BinderInternal_getContextObject },
// Leo, take android_os_BinderInternal_joinThreadPool Methods and com.android.internal.os.BinderInternal.joinThreadPool Method to bind
{ "joinThreadPool", "()V", (void*)android_os_BinderInternal_joinThreadPool },
// Leo, take android_os_BinderInternal_disableBackgroundScheduling Methods and com.android.internal.os.BinderInternal.disableBackgroundScheduling Method to bind
{ "disableBackgroundScheduling", "(Z)V", (void*)android_os_BinderInternal_disableBackgroundScheduling },
// Leo, take android_os_BinderInternal_setMaxThreads Methods and com.android.internal.os.BinderInternal.setMaxThreads Method to bind
{ "setMaxThreads", "(I)V", (void*)android_os_BinderInternal_setMaxThreads },
// Leo, take android_os_BinderInternal_handleGc Methods and com.android.internal.os.BinderInternal.handleGc Method to bind
{ "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 The assignment is BinderInternal.java file
gBinderInternalOffsets.mClass = MakeGlobalRefOrDie(env, clazz);
gBinderInternalOffsets.mForceGc = GetStaticMethodIDOrDie(env, clazz, "forceBinderGc", "()V");
// Leo, register JNI function
return RegisterMethodsOrDie(
env, kBinderInternalPathName,
gBinderInternalMethods, NELEM(gBinderInternalMethods));
}
static struct binderinternal_offsets_t
{
// Class state.
jclass mClass;
jmethodID mForceGc;
} gBinderInternalOffsets;
gBinderInternalOffsets.mClass and Java World com.android.internal.os.BinderInternal class
gBinderInternalOffsets.mForceGc and com.android.internal.os.BinderInternal Class forceBinderGc Methods corresponding to the
And will gBinderInternalMethods The corresponding Java The way of the world and C The world correspondence method corresponds one by one
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 and Java World android.os.BinderProxy class
gBinderProxyOffsets.mConstructor and android.os.BinderProxy Class init Methods corresponding to the
gBinderProxyOffsets.mSendDeathNotice and android.os.BinderProxy Class sendDeathNotice Methods corresponding to the
gBinderProxyOffsets.mSelf and android.os.BinderProxy Class mSelf Object correspondence
gBinderProxyOffsets.mObject and android.os.BinderProxy Class mObject Object correspondence
And will gBinderProxyMethods The corresponding Java The way of the world and C The world correspondence method corresponds one by one
2. BinderInternal.getContextObject Function analysis
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();
It's called native Layer of getContextObject Method , Remember the previous Binder Of JNI In registration , Registered BinderInternal Methods? ?
static const JNINativeMethod gBinderInternalMethods[] = {
/* name, signature, funcPtr */
// Leo, take android_os_BinderInternal_getContextObject Methods and com.android.internal.os.BinderInternal.getContextObject Method to bind
{ "getContextObject", "()Landroid/os/IBinder;", (void*)android_os_BinderInternal_getContextObject },
// Leo, take android_os_BinderInternal_joinThreadPool Methods and com.android.internal.os.BinderInternal.joinThreadPool Method to bind
{ "joinThreadPool", "()V", (void*)android_os_BinderInternal_joinThreadPool },
// Leo, take android_os_BinderInternal_disableBackgroundScheduling Methods and com.android.internal.os.BinderInternal.disableBackgroundScheduling Method to bind
{ "disableBackgroundScheduling", "(Z)V", (void*)android_os_BinderInternal_disableBackgroundScheduling },
// Leo, take android_os_BinderInternal_setMaxThreads Methods and com.android.internal.os.BinderInternal.setMaxThreads Method to bind
{ "setMaxThreads", "(I)V", (void*)android_os_BinderInternal_setMaxThreads },
// Leo, take android_os_BinderInternal_handleGc Methods and com.android.internal.os.BinderInternal.handleGc Method to bind
{ "handleGc", "()V", (void*)android_os_BinderInternal_handleGc }
};
getContextObject and android_util_Binder.cpp In the document android_os_BinderInternal_getContextObject Methods corresponding to the
static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
{
// Leo, The return is new BpBinder(0)
sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
// Leo, The method is JNI Application , The return is BinderProxy
return javaObjectForIBinder(env, b);
}
Two methods are called here , So let's look at it one by one
3. ProcessState Of getContextObject Method
ProcessState.cpp
sp<ProcessState> ProcessState::self()
{
Mutex::Autolock _l(gProcessMutex);
if (gProcess != NULL) {
return gProcess;
}
// Leo, initialization ProcessState object
gProcess = new ProcessState;
return gProcess;
}
OK, The singleton pattern , initialization ProcessState
ProcessState::ProcessState()
: mDriverFD(open_driver()) // Leo, open binder equipment
, 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, by binder Devices allocate address space
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 Initializing , Open the /dev/binder equipment , And allocate address space to the device
Next , Call its getContextObject Method
sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
{
return getStrongProxyForHandle(0);
}
Next
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);
}
From here on , First call lookupHandleLocked Method , Because this is the first call , So create a new handle_entry, And back to , Moreover, its binder and refs by NULL
that getStrongProxyForHandle Method and then go down , because binder by NULL,mHandle What's coming in is 0, So enter the judgment condition , Last new BpBinder, And the parameter is 0
therefore ,
sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
The return is new BpBinder(0)
4. javaObjectForIBinder Method resolution
// Leo, val by new BpBinder(0)
jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val)
{
// Leo, Not for NULL
if (val == NULL) return NULL;
/*
* Leo, because BpBinder No inheritance Binder Of checkSubclass Method
* So the call is Binder.cpp Medium checkSubclass Method , return 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, First time in , Obviously not
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 The assignment is 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;
}
Incoming parameter , We just analyzed , The second parameter is new BpBinder(0), and BpBinder Without inheriting a parent class checkSubclass Method , So the method of its parent class is called , return false
and jobject object = (jobject)val->findObject(&gBinderProxyOffsets); for the first time , Obviously NULL, therefore , Then down
gBinderProxyOffsets.mClass, This , We had an analysis before Binder Of JNI register , Confirm that the value is android.os.BinderProxy
gBinderProxyOffsets.mConstructor, How to construct it
therefore , The statement returns Java The object of the layer BinderProxy
Next ,
env->SetLongField(object, gBinderProxyOffsets.mObject, (jlong)val.get());
take new BpBinder(0) Assign a value to gBinderProxyOffsets.mObject
thus , Whole BinderInternal.getContextObject The process of , Analysis here , It's clear , Initialize and return BinderProxy object , And will BinderInternal Of mObject The object is assigned the value new BpBinder(0)
版权声明
本文为[Tianwang gaidihu 626]所创,转载请带上原文链接,感谢
边栏推荐
- Do these mistakes in your resume affect your annual salary of one million?
- 新型存算一体芯片诞生,利好人工智能应用~
- TypeScript(1-2-2)
- 京东落地DevOps平台时爆发的冲突如何解决?
- 前后端分离跨域问题解决方案
- Talk about go code coverage technology and best practices
- read文件一个字节实际会发生多大的磁盘IO?
- Golang ICMP Protocol detects viable hosts
- 关于adb连接手机offline的问题解决
- On the concurrency of update operation
猜你喜欢
c++ opencv4.3 sift匹配
write文件一个字节后何时发起写磁盘IO
腾讯:阿里的大中台虽好,但也不是万能的!
进入互联网得知道的必备法律法规有哪些?
Is there no way out for older programmers?
The birth of a new integrated memory and computing chip is conducive to the application of artificial intelligence~
总结: 10月海外DeFi新项目,更多资管策略来了!
第二章编程练习
The first open source Chinese Bert pre training model in the financial field
前后端分离跨域问题解决方案
随机推荐
Huawei has an absolute advantage in the 5g mobile phone market, and the market share of Xiaomi is divided by the market survey organization
svg究竟是什么?
We made a medical version of the MNIST dataset, and found that the common automl algorithm is not so easy to use
我用 Python 找出了删除我微信的所有人并将他们自动化删除了
数据库连接报错之IO异常(The Network Adapter could not establish the connection)
浅谈,盘点历史上有哪些著名的电脑病毒,80%的人都不知道!
学习记录并且简单分析
2020-11-05
性能压测时,并发压力增加,系统响应时间和吞吐量如何变化
read文件一个字节实际会发生多大的磁盘IO?
[open source]. Net uses ORM to access Huawei gaussdb database
软件开发中如何与人协作? | 每日趣闻
python开发qt程序读取图片的简单流程
二叉树的四种遍历方应用
Builder pattern
.NET 大数据量并发解决方案
On the software of express delivery cabinet and deposit cabinet under Windows
. net large data concurrency solution
Summary of rendering of water wave and caustics (etching) in webgl
10 common software architecture patterns