Binder Inter-process communication detailed

Source: Internet
Author: User

Objective

Interlacing as Foster, the same sentence applies at any time, the same professional, deep down, the difference is also huge. Today, talk about how you learn about the mechanics of binder interprocess communication. At first, it was only known that Binder was a very low-level thing, and it was not even clear what was being used.

There are two main ways of doing this:

    • Read the binder posts written by others.
      The purpose is very simple, probably understand what binder is a thing, what core things, for the source of the time to see the selective filtering is helpful, it is best to look at the bottom of the picture under the Mind map summary or you can draw a flowchart.

    • See Binder Source code
      For the point of entry, start with the most familiar client, choose typical concrete examples, and analyze the key points that you see in front of others.

Binder World Portal
    • Learning how to use things and thinking about why to create things is completely different, and many people write articles that tend to ignore the latter.

What do you need to do if two processes need to communicate with each other? Suppose one of the processes is a client process and the other is a server-side process, where the contract is referred to as the client and server.

    • 1. The client needs to know which is the service-side method he wants to invoke.
    • 2. How the client passes and receives data to the server.
    • 3. Block the details of the underlying communication, including data exchange through shared memory.

The first question is simple, get a unique identifier, through the package name + class name.
The second problem is that you can use classes that implement the Parcelable interface, why? This is because the Android system can decompose objects into primitives that can be grouped into processes.
The third problem, encapsulating a class to the concrete implementation, his name is binder, and then this binder word needs to be inherited by the server.

Look at the source code to find a good point
    • Since binder is an important part of the Android system, Binder is very large from the source, so finding a good entry point becomes very important. Just so-called, walnuts, posterity, refer to a thorough understanding of the Android Binder Communication architecture This article, the pointcut is StartService start, the specific analysis is the process of client process call server process.

[=> Activitymanagernative::activitymanagerproxy]

public ComponentName startService(IApplicationThread caller, Intent service,            String resolvedType, int userId) throws RemoteException    {        //这一步操作主要实例了两个Parcel对象,datat是客户端的发送数据,reply是服务端返回的数据         //具体参考:Parcel的obtain和recycle方法        Parcel data = Parcel.obtain();        Parcel reply = Parcel.obtain();        data.writeInterfaceToken(IActivityManager.descriptor);        data.writeStrongBinder(caller != null ? caller.asBinder() : null);        service.writeToParcel(data, 0);        data.writeString(resolvedType);        data.writeInt(userId);        //        mRemote.transact(START_SERVICE_TRANSACTION, data, reply, 0);        reply.readException();        ComponentName res = ComponentName.readFromParcel(reply);        //具体参考:Parcel的obtain和recycle方法        data.recycle();        reply.recycle();        return res;    }
Obtain and recycle methods of parcel
    • These two methods look familiar with the name, is there? The message generated in the previous handler also has these two methods, the perception tells me that the principle of the two places is the same, the heartbeat than action, immediately into the verification link.
Obtain method

[=> Parcel.java::obtain]

    private static final int pool_size = 6;    private static final parcel[] Sownedpool = new Parcel[pool_size];  .../** * Description: This pool is a 6-capacity Parcel array declared above, omitting several codes in the method * Retrieve a new Parcel object from this pool */public static        Parcel obtain () {final parcel[] pool = sownedpool;            Synchronized (pool) {Parcel p;                for (int i=0; i<pool_size; i++) {p = pool[i];                    if (P! = null) {Pool[i] = null;                return p;    }}}//Here The parameter is passed 0 return new Parcel (0);    } ... private Parcel (int nativeptr) {init (nativeptr);            } private void init (int nativeptr) {if (nativeptr! = 0) {mnativeptr = NativePtr;        Mownsnativeparcelobject = false; } else {//nativecreate is a native method, refer to: Nativecreate method, mnativeptr This is understandable as pointer mnativeptr = Nativecreate ()            ; MownsnativeparceLOBject = true;        }} private void FreeBuffer () {if (mownsnativeparcelobject) {nativefreebuffer (mnativeptr); }    }
    • Obtain method: If the cache parcel array is not empty, use the cached array, or the home creates a parcel.
Nativecreate method

[=> Android_os_parcel.cpp::android_os_parcel_create]

/***这里来看的话,很清楚的看到返回的是parcel的指针**/static jint android_os_Parcel_create(JNIEnv* env, jclass clazz){    Parcel* parcel = new Parcel();    return reinterpret_cast<jint>(parcel);}
Recycle method

[=> Parcel.java::recycle]

 /** * Put a parcel object back in the pool. This object is not required until this callback.     You must don't touch * The object after this call.        */public final void Recycle () {//This method internally tune is the native method, in fact, according to the pointer to release memory FreeBuffer ();        Final parcel[] pool;        This is actually the assignment of True if (mownsnativeparcelobject) {pool = Sownedpool) during the instantiation creation process in the obtain parameterless method;            The else {//mnativeptr can be seen as a pointer to a parcel object, and Sholderpool is also a 6-capacity parcel array mnativeptr = 0;        Pool = Sholderpool;  }//Put in the cache array synchronized (pool) {for (int i=0; i<pool_size; i++) {if (Pool[i]                    = = null) {Pool[i] = this;                Return            }}}} ... private void FreeBuffer () {if (mownsnativeparcelobject) {        Nativefreebuffer (MNATIVEPTR); }    }
    • Recycle method: According to the value of Mownsnativeparcelobject, if true, the object is obtained without the obtain method of the parameter, put it in Sownedpool, or nativeptr with obtain (int obj) The NativePtr method gets the object that the pointer is pointing to and puts it into the sholderpool.

After looking at the source code found, in fact, this principle is similar, the way the cache is different, the message is through the chain list way to proceed, parcel is through a fixed array, the same kind of wonderful.

Quest Mremote

Code involved: There are two problems to solve, one is where Mremote come from, and the other is the Transact method of mremote.

Mremote.transact (start_service_transaction, data, reply, 0);

Where does mremote come from?
    • The search finds that the ActivityManagerProxy constructor method of the class is assigned, and ActivityManagerProxy(AMP) this class is called by the asInterface method.

[-> Activitymanagernative.java::asinterface]

public abstract class ActivityManagerNative extends Binder implements IActivityManager {    static public IActivityManager asInterface(IBinder obj) {        if (obj == null) {            return null;        }        //此处obj = BinderProxy, descriptor = "android.app.IActivityManager";        IActivityManager in = (IActivityManager)obj.queryLocalInterface(descriptor);        if (in != null) { //此处为null            return in;        }        return new ActivityManagerProxy(obj);    }    ...}

At this point obj is the Binderproxy object, which records the handle of the binder thread of the AMS service in the remote process system_server.

[-> Activitymanagernative.java::activitymanagerproxy]

class ActivityManagerProxy implements IActivityManager{    public ActivityManagerProxy(IBinder remote){        mRemote = remote;    }}

Mremote is the Binderproxy object that points to the AMS service.

The Transact method of Mremote

[-> Binder.java::binderproxy]

final class BinderProxy implements IBinder {    public native boolean transact(int code, Parcel data, Parcel reply,            int flags) throws RemoteException;

Mremote actually calls the BinderProxy method transact , and transact calls the native method mRemote.transact() method, through the JNI call android_os_BinderProxy_transact method.

Android_os_binderproxy_transact

[-> Android_util_binder.cpp]

static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,    jint code, jobject dataObj, jobject replyObj, jint flags){    ...    //将java Parcel转为c++ Parcel    Parcel* data = parcelForJavaObject(env, dataObj);    Parcel* reply = parcelForJavaObject(env, replyObj);    //gBinderProxyOffsets.mObject中保存的是new BpBinder(handle)对象    IBinder* target = (IBinder*) env->GetLongField(obj, gBinderProxyOffsets.mObject);    ...    //此处便是BpBinder::transact()    status_t err = target->transact(code, *data, reply, flags);    ...    //最后根据transact执行具体情况,抛出相应的Exception    signalExceptionForError(env, obj, err, true , data->dataSize());    return JNI_FALSE;}

The Bpbinder object is saved in Gbinderproxyoffsets.mobject, which is zygote called Androidruntime::startreg method to complete the registration of the JNI method when booting.

where the Register_android_os_binder () process has an initial and registered Binderproxy operation to complete the gbinderproxyoffsets assignment process. Next, enter the method.

Follow-up Analysis = =

Resources

Simple, concise and thorough understanding of binder

Thorough understanding of Android Binder Communication architecture

An article about Brief Encounter's Android Binder interprocess communication mechanism

Binder Inter-process communication detailed

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.