当前位置:网站首页>(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]所创,转载请带上原文链接,感谢
边栏推荐
- 2020-11-05
- 框架-SPI四种模式+通用设备驱动实现-源码
- 阿里云视频云技术专家 LVS 演讲全文:《“云端一体”的智能媒体生产制作演进之路》
- Mac环境安装Composer
- Welcome to offer, grade P7, face-to-face sharing, 10000 words long text to take you through the interview process
- Interpretation of deepmind's latest paper: the causal reasoning algorithm in discrete probability tree is proposed for the first time
- Is there no way out for older programmers?
- C + + things: from rice cookers to rockets, C + + is everywhere
- Golang ICMP协议探测存活主机
- Returning to the third place in the world, what did Xiaomi do right?
猜你喜欢
Arduino ide build esp8266 development environment, slow file download solution | esp-01 make WiFi switch tutorial, transform dormitory lights
The birth of a new integrated memory and computing chip is conducive to the application of artificial intelligence~
基于阿里云日志服务快速打造简版业务监控看板
“他,程序猿,35岁,被劝退”:不要只懂代码,会说话,胜过10倍默默努力
技术总监7年总结,如何进行正确的沟通?
GopherChina 2020大会
C + + things: from rice cookers to rockets, C + + is everywhere
第五章编程题
学习记录并且简单分析
I used Python to find out all the people who deleted my wechat and deleted them automatically
随机推荐
性能压测时,并发压力增加,系统响应时间和吞吐量如何变化
Golang ICMP Protocol detects viable hosts
VIM configuration tutorial + source code
I used Python to find out all the people who deleted my wechat and deleted them automatically
Don't release resources in finally, unlock a new pose!
On the concurrency of update operation
苏州游记
Blockchain weekly: the development of digital currency is written into the 14th five year plan; Biden invited senior adviser of MIT digital currency program to join the presidential transition team; V
契约式设计(Dbc)以及其在C语言中的应用
Alibaba cloud accelerates its growth and further consolidates its leading edge
软件开发中如何与人协作? | 每日趣闻
打工人,打工魂,抽终身会员,成为人上人!
阿里云视频云技术专家 LVS 演讲全文:《“云端一体”的智能媒体生产制作演进之路》
Recurrence of Apache kylin Remote Code Execution Vulnerability (cve-2020-1956)
Station B STM32 video learning
How does the system response time and throughput change with the increase of concurrency pressure during performance pressure testing
Liteos message queuing
Restfulapi learning notes -- father son resources (4)
TypeScript(1-2-2)
华为在5G手机市场占据绝对优势,市调机构对小米的市占出现分歧