当前位置:网站首页>(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]所创,转载请带上原文链接,感谢
边栏推荐
猜你喜欢
How to solve the conflict when JD landed on Devops platform?
Rabbitmq (1) - basic introduction
Travel notes of Suzhou
总结: 10月海外DeFi新项目,更多资管策略来了!
Liteos message queuing
构建者模式(Builder pattern)
I used Python to find out all the people who deleted my wechat and deleted them automatically
API生命周期的5个阶段
学习记录并且简单分析
这几个C++的坑,一旦踩中了,加班是肯定避免不了了!
随机推荐
我用 Python 找出了删除我微信的所有人并将他们自动化删除了
Rabbitmq (1) - basic introduction
我用 Python 找出了删除我微信的所有人并将他们自动化删除了
Learn to record and analyze
svg究竟是什么?
Js中常见的内存泄漏场景
Gopherchina 2020 Conference
Summary of template engine
浅谈,盘点历史上有哪些著名的电脑病毒,80%的人都不知道!
How to cooperate with people in software development? |Daily anecdotes
Liteos message queuing actual combat
性能压测时,并发压力增加,系统响应时间和吞吐量如何变化
On the software of express delivery cabinet and deposit cabinet under Windows
浅谈OpenGL之DSA
I used Python to find out all the people who deleted my wechat and deleted them automatically
10个常见的软件架构模式
阿里云加速增长,进一步巩固领先优势
How to make a correct summary for 7 years?
SQL quick query
python开发qt程序读取图片的简单流程