from :https://blog.csdn.net/moonshine2016/article/details/54378358
Reference resources :https://www.jianshu.com/p/9c023701c261
A colleague asked me a few days ago Java Layer of Binder and Java Layer of ServiceManager and C++ Layer of ServiceManager How does it correspond to , It's just that I said , If you don't pay attention for a period of time, you will feel strange , Now to sum up , Just write Java Layer of ,C++ The layer does not write ,C++ Binder We need to master the knowledge of ,java and native The basic concepts and corresponding relations of the two are not mentioned .
Java layer Binder The initialization process
Binder The final thing is to deal with its drivers ,Java The layer should be adjusted Linux Things in the kernel layer have to go through native Method , And for android System services ,native and java Corresponding , There's always a registration process , Let's see where the registration is implemented
JNI Binder Registration of
Zygote When it starts :
app_main.cpp
int main(int argc, char* const argv[])
{
......
AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
......
if (zygote) {
runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
}
......
}
AppRuntime yes AndroidRuntime Subclasses of , It doesn't cover itself start Method , So I'm going to see AndroidRuntime Class start Method
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
......
/*
* Register android functions.
*/
if (startReg(env) < 0) {
ALOGE("Unable to register all android natives\n");
return;
}
......
}
/*
* Register android native functions with the VM.
*/
/*static*/ int AndroidRuntime::startReg(JNIEnv* env)
{
......
if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {
env->PopLocalFrame(NULL);
return -1;
}
......
}
gRegJNI Is an array :
static const RegJNIRec gRegJNI[] = {
......
REG_JNI(register_android_os_Binder),
......
};
REG_JNI Is a macro definition
#ifdef NDEBUG
#define REG_JNI(name) { name }
struct RegJNIRec {
int (*mProc)(JNIEnv*);
};
#else
#define REG_JNI(name) { name, #name }
struct RegJNIRec {
int (*mProc)(JNIEnv*);
const char* mName;
};
#endif
gRegJNI It's a RegJNIRec Array of , therefore gRegJNI That's how it's defined :
static const RegJNIRec gRegJNI[] = {
......
{ register_android_os_Binder },
......
};
register_jni_procs Function as follows :
static int register_jni_procs(const RegJNIRec array[], size_t count, JNIEnv* env)
{
for (size_t i = 0; i < count; i++) {
if (array[i].mProc(env) < 0) {
#ifndef NDEBUG
ALOGD("----------!!! %s failed to load\n", array[i].mName);
#endif
return -1;
}
}
return 0;
}
It's a loop call gRegJNI Functions in arrays , At this time register_android_os_Binder(env) It's called .
register_android_os_Binder stay AndroidRuntime.cpp Is declared as extern:
extern int register_android_os_Binder(JNIEnv* env);
1
The place to achieve it is in android_util_Binder.cpp in :
int register_android_os_Binder(JNIEnv* env)
{
if (int_register_android_os_Binder(env) < 0)
return -1;
if (int_register_android_os_BinderInternal(env) < 0)
return -1;
if (int_register_android_os_BinderProxy(env) < 0)
return -1;
......
return 0;
}
From the name , It has to be connected to 3 individual Java Class , Namely Binder, BinderInternal and BinderProxy, One by one, it seems :
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));
}
Associated with the android.os.Binder class , And will use this class of mExecTransact Domain and execTransact Method , Save it to gBinderOffsets In the object , That means native Will save a value to mExecTransact in , Will the callback execTransact Method .
const char* const kBinderInternalPathName = "com/android/internal/os/BinderInternal";
static int int_register_android_os_BinderInternal(JNIEnv* env)
{
jclass clazz = FindClassOrDie(env, kBinderInternalPathName);
gBinderInternalOffsets.mClass = MakeGlobalRefOrDie(env, clazz);
gBinderInternalOffsets.mForceGc = GetStaticMethodIDOrDie(env, clazz, "forceBinderGc", "()V");
return RegisterMethodsOrDie(
env, kBinderInternalPathName,
gBinderInternalMethods, NELEM(gBinderInternalMethods));
}
Associated with the java Of com.android.internal.os.BinderInternal class , Saved it forceBinderGc Method .
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));
}
This method is longer , The saved Java There are also more things , It is worth noting that , It also preserved BinderProxy Constructor for , In other words, it may take the initiative to new One BinderProxy Examples come out .
See, so far ,native Of Binder To correspond to Java Of 3 Of the classes , Namely android.os.Binder,com.android.internal.os.BinderInternal and android.os.BinderProxy. For ease of reading , Summarize their corresponding relationship in the form of class diagram :
take Java Layer services are registered with ServiceManager The process in
We know ,native Layer of Binder Yes Bn and Bp The said ,Bn Should be Binder Native Abbreviation , It's local implementation Binder It can also be said that C/S Medium S,Bp yes Binder Proxy Abbreviation , amount to C.
With PackageManagerService For example :
public static PackageManagerService main(Context
......
PackageManagerService m = new PackageManagerService(context, installer,
factoryTest, onlyCore);
......
ServiceManager.addService("package", m);
return m;
}
public static void addService(String name, IBinder service) {
try {
getIServiceManager().addService(name, service, false);
} catch (RemoteException e) {
Log.e(TAG, "error in addService", e);
}
}
getIServiceManager Back to a IServiceManager class , And it's a single example , The last thing to call is
private static IServiceManager getIServiceManager() {
if (sServiceManager != null) {
return sServiceManager;
}
// Find the service manager
sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
return sServiceManager;
}
The above code brings Three questions , One is BinderInternal.getContextObject(), One is ServiceManagerNative.asInterface, The other is addService The role of :
BinderInternal.getContextObject() The essence of
ServiceManagerNative.asInterface The parameter in is BinderInternal.getContextObject(), Look, it's native Method , Corresponding native The code is just in sight android_util_Binder.cpp In file :
static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
{
// It's a BpBinder
sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
return javaObjectForIBinder(env, b);
}
jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val)
{
if (val == NULL) return NULL;
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?
// 1
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);
}
//2
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.
//3
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));
......
// Note that a new object reference has been created.
//4
android_atomic_inc(&gNumProxyRefs);
incRefsCreated(env);
}
return object;
}
First judge and Java Layer related Native Layer of BpBinder Whether there is , If there is , Delete .
Then create a Java Layer of BinderProxy example .
take Native Layer of BpBinder The pointer is saved to java BinderProxy Example of mObject Field , This way BinderProxy Of mObject Fields can be operated on Native Layer of BpBinder 了 .
Atoms increase gNumProxyRefs and gNumRefsCreated The number of , When gNumRefsCreated The value of exceeds 200, Will call BinderInternal Of forceBinderGc Method .
Sum up :
Created a Native Layer of BpBinder;
take BpBinder Save the pointer to BinderProxy Of mObject, and BpBinder The object of communication is Native Of ServiceManager, This is Java and Native Of ServiceManager It's a foreshadowing for our communications .
Can be BinderProxy succeed in negotiation Java Layer of Bp End .
ServiceManagerNative.asInterface The role of
static public IServiceManager asInterface(IBinder obj)
{
if (obj == null) {
return null;
}
//1
IServiceManager in =
(IServiceManager)obj.queryLocalInterface(descriptor);
if (in != null) {
return in;
}
//2
return new ServiceManagerProxy(obj);
}
obj yes Native Instantiated BinderProxy object ,BinderProxy Code in Binder.java in , and Binder In the same file .queryLocalInterface The return value of is null.
Instantiate a ServiceManagerProxy object , There is one in this example IBinder Type of mRemote Field , This field holds BinderProxy example .
public ServiceManagerProxy(IBinder remote) {
mRemote = remote;
}
summary :
ServiceManagerNative.asInterface The return is ServiceManagerProxy Example , This instance implements IServiceManager The interface of .
ServiceManagerProxy Pass through mRemote The fields are saved BinderProxy, That is to say Java Layer of Bp End .
addService The role of
There is an analysis , When calling ServiceManager.addService when , It's actually calling theta ServiceManagerProxy Class addService,ServiceManagerProxy Class is located ServiceManagerNative.java In file .
public void addService(String name, IBinder service, boolean allowIsolated)
throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IServiceManager.descriptor);
data.writeString(name);
data.writeStrongBinder(service);
data.writeInt(allowIsolated ? 1 : 0);
//1
mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);
reply.recycle();
data.recycle();
}
mRemote That is to say BinderProxy, It will be called transactNative,transactNative It's a native Method , Then look at this method .
static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,
//1
IBinder* target = (IBinder*)
env->GetLongField(obj, gBinderProxyOffsets.mObject);
if (target == NULL) {
jniThrowException(env, "java/lang/IllegalStateException", "Binder has been finalized!");
return JNI_FALSE;
}
//2
status_t err = target->transact(code, *data, reply, flags);
......
return JNI_FALSE;
}
Take it out and store it in BinderProxy Medium BpBinder Object pointer
towards Native Layer of ServiceManager Send a request
summary :
Java Layer calls ServiceManger.addService after , In the end, it's to Native Layer of ServiceManager Asking for additional services .
Native Layer of ServiceManager There is only one , and java Layer of ServiceManager be relative to Native Of ServiceManager It's just C End , such , Whether it's through Native add service Or through java add service, Whole Android You can get this service Of Binder.
Java Service Terminal Bp Where is the
And then there's a question , When calling ServiceManager.addService When it came in Service It should correspond to Native Of BnBinder ah , Now how to reflect the corresponding relationship ? This relationship needs to be reconsidered addService 了 .
addService The second parameter is of type IBinder, It's an interface , Its implementation class is Binder,java The upper layer can call addService When adding services , All the examples are Binder, according to java The rules of , Just instantiate , The corresponding constructor of its parent class must be called :
public Binder() {
init();
......
}
init() yes native Method , In fact, now android_util_Binder.cpp in :
static void android_os_Binder_init(JNIEnv* env, jobject obj)
{
JavaBBinderHolder* jbh = new JavaBBinderHolder();
...
env->SetLongField(obj, gBinderOffsets.mObject, (jlong)jbh);
}
new One native Layer of JavaBBinderHolder, And save it to Binder Of mObject in . Watch out! , although native Layer of gBinderOffsets.mObject It's a static Of , but java Layer of Binder Of mObject Is not static Of course , That is to say, each Binder Instance has one Native Of JavaBBinderHolder Object pointer .
JavaBBinderHolder Class is declared as follows :
class JavaBBinderHolder : public RefBase
{
}
No inheritance BBinder, Still didn't find out what it was Bn The trace of the end , Need to be review Let's go through the previous process , look down ServiceManagerProxy What happens when you add a service :
public void addService(String name, IBinder service, boolean allowIsolated)
throws RemoteException {
Parcel data = Parcel.obtain();
......
data.writeStrongBinder(service);
......
}
writeStrongBinder Questionable
writeStrongBinder What happened?
Parcel The function is as follows :
public final void writeStrongBinder(IBinder val) {
nativeWriteStrongBinder(mNativePtr, val);
}
nativeWriteStrongBinder Implementation in android_os_Parcel.cpp in :
static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr, jobject object)
{
Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
if (parcel != NULL) {
const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object));
if (err != NO_ERROR) {
signalExceptionForError(env, clazz, err);
}
}
}
Called a ibinderForJavaObject function , This function is located in android_util_Binder.cpp in
sp<IBinder> ibinderForJavaObject(JNIEnv* env, jobject obj)
{
if (obj == NULL) return NULL;
if (env->IsInstanceOf(obj, gBinderOffsets.mClass)) {
JavaBBinderHolder* jbh = (JavaBBinderHolder*)
env->GetLongField(obj, gBinderOffsets.mObject);
return jbh != NULL ? jbh->get(env, obj) : NULL;
}
if (env->IsInstanceOf(obj, gBinderProxyOffsets.mClass)) {
return (IBinder*)
env->GetLongField(obj, gBinderProxyOffsets.mObject);
}
ALOGW("ibinderForJavaObject: %p is not a Binder object", obj);
return NULL;
}
Incoming obj yes Binder example , So just created JavaBBinderHolder Of get Function will be called :
sp<JavaBBinder> get(JNIEnv* env, jobject obj)
{
AutoMutex _l(mLock);
sp<JavaBBinder> b = mBinder.promote();
if (b == NULL) {
b = new JavaBBinder(env, obj);
mBinder = b;
ALOGV("Creating JavaBinder %p (refs %p) for Object %p, weakCount=%" PRId32 "\n",
b.get(), b->getWeakRefs(), obj, b->getWeakRefs()->getWeakCount());
}
return b;
}
The return is JavaBBinder example ,
JavaBBinder Inherited BBinder, So finally add it to Native ServiceManager This is the object in , Summarize their class diagrams :
Java Layer of Binder The object owns Native JavaBBinderHolder Object pointer ,JavaBBinderHolder Yes JavaBBinder The object of , and JavaBBinder And then there is Java layer Binder The object of .