当前位置:网站首页>(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]所创,转载请带上原文链接,感谢
边栏推荐
- Millet and oppo continue to soar in the European market, and Xiaomi is even closer to apple
- markdown使用
- Solution of DEV-C + + unable to debug in Windows Environment
- 搭载固态硬盘的服务器究竟比机械硬盘快多少
- 函数分类大pk!sigmoid和softmax,到底分别怎么用?
- Huawei has an absolute advantage in the 5g mobile phone market, and the market share of Xiaomi is divided by the market survey organization
- B站stm32视频学习
- 小米、OPPO在欧洲市场继续飙涨,小米更是直逼苹果
- Xiaoqingtai officially set foot on the third day of no return
- Workers, workers soul, draw lifelong members, become a person!
猜你喜欢
京东落地DevOps平台时爆发的冲突如何解决?
GopherChina 2020大会
Stm32uberide download and install - GPIO basic configuration operation - debug (based on CMSIS DAP debug)
The birth of a new integrated memory and computing chip is conducive to the application of artificial intelligence~
小米、OPPO在欧洲市场继续飙涨,小米更是直逼苹果
我用 Python 找出了删除我微信的所有人并将他们自动化删除了
Learn to record and analyze
[开源] .Net 使用 ORM 访问 华为GaussDB数据库
rabbitmq(一)-基础入门
构建者模式(Builder pattern)
随机推荐
SQL 速查
喜获蚂蚁offer,定级p7,面经分享,万字长文带你走完面试全过程
jsliang 求职系列 - 07 - Promise
关于update操作并发问题
Elasticsearch learning one (basic introduction)
RestfulApi 学习笔记——父子资源(四)
PHP生成唯一字符串
使用K3S创建本地开发集群
The first open source Chinese Bert pre training model in the financial field
软件开发中如何与人协作? | 每日趣闻
Liteos message queuing
On the software of express delivery cabinet and deposit cabinet under Windows
函数分类大pk!sigmoid和softmax,到底分别怎么用?
Elasticsearch 学习一(基础入门).
Interpretation of deepmind's latest paper: the causal reasoning algorithm in discrete probability tree is proposed for the first time
python开发qt程序读取图片的简单流程
Tips and skills of CSP examination
vim-配置教程+源码
Application of four ergodic square of binary tree
I used Python to find out all the people who deleted my wechat and deleted them automatically