Analyze the Java layer's ServiceManager to see how binder is implemented in the Java layer.
Public final class ServiceManager { private static final String TAG = "ServiceManager"; private static Iservicemanager Sservicemanager;//iservicemanager is an interface that defines a common (public) method. private static hashmap<string, ibinder> Scache = new hashmap<string, ibinder> ();//cache, its value is IBinder ... Public static IBinder GetService (String name) { try { IBinder service = scache.get (name);//First find if from cache ( Service! = null) { return service; } else { return Getiservicemanager (). GetService (name);//Generate a new IBinder } } catch (RemoteException e) { log.e (TAG, "Error in GetService", e); } return null; }
...
The ServiceManager here is just a package whose member variables and methods are static. From the above Scache saved key value pairs and GetService return value type IBinder (unlike the C + + layer IBinder) can be seen, through ServiceManager is a IBinder type object, through the analysis of the following, You can actually see that it is a Bpbinder object.
private static Iservicemanager Getiservicemanager () {if (Sservicemanager! = null) {return sservice Manager; }//Find the service Manager Sservicemanager = Servicemanagernative.asinterface (Binderinternal.getcontextob Ject ());//Find Iservicemanager object and return to Sservicemanager; } .../** * Return the Global "context object" of the system. This is usually * a implementation of Iservicemanager, which you can use for Find * other services. */public static final native IBinder Getcontextobject ();//binderinternale: Call native function, return IBinder object ... static public I ServiceManager asinterface (IBinder obj)//Incoming is the IBinder object above, remember that this is the Java object {if (obj = = null) {return n Ull } Iservicemanager in = (Iservicemanager) obj.querylocalinterface (descriptor);//Find from IBinder object and convert to IService Manager Object if (in! = null) {return in; } return new Servicemanagerproxy (oBJ);//If not found, a Servicemanageporxy object is generated using the incoming IBinder object}
Above a circle, directly from the Servicemanagerproxy view, there are two aspects: 1, get a native layer of an object, and converted to IBinder, that is, the above native IBinder Getcontextobject (); 2, Use the obtained ibinder to generate a Servicemanagerproxy object. Here's a look at how Servicemanagerproxy is constructed:
Public Servicemanagerproxy (IBinder remote) { Mremote = Remote;//mremote is the IBinder type, where the incoming IBinder object is saved in Mremote }
Public IBinder GetService (String name) throws RemoteException { Parcel data = Parcel.obtain (); Parcel reply = Parcel.obtain (); Data.writeinterfacetoken (iservicemanager.descriptor); Data.writestring (name); Mremote.transact (get_service_transaction, data, reply, 0);//finally use IBinder's transact to transmit data ibinder binder = Reply.readstrongbinder (); Reply.recycle (); Data.recycle (); return binder; }
Summary: Calling ServiceManager's GetService () generates a Servicemanagerproxy object that holds a mremote (IBinder), The Mremote (which is represented by the Bpbinder in the Java layer) can send data to the lower level.
Getcontextobject Analysis:
public static final native IBinder Getcontextobject ();//binderinternale: Call native function, return IBinder object-corresponds to this function:
Static Jobject Android_os_binderinternal_getcontextobject (jnienv* env, Jobject clazz) { sp<ibinder> B = Processstate::self ()->getcontextobject (NULL);//Go here: B is a bpbinder return Javaobjectforibinder (env, b);// Returns the binderproxy of a Java layer
Here we understand that the above Mremote hold the Binderproxy object. The Transact () method that calls the Mremote object above is the Transact method that calls Binderproxy:
Public native Boolean transact (int code, PARCEL data, Parcel reply, int flags) throws Remoteexception;...static Jboole An android_os_binderproxy_transact (jnienv* env, Jobject obj, jint code, Jobject dataobj, Jobject replyobj, Jint flags )//Throws remoteexception{ if (dataobj = = null) { jnithrownullpointerexception (env, NULL); return jni_false; } parcel* data = Parcelforjavaobject (env, dataobj); if (data = = NULL) { return jni_false; } parcel* reply = Parcelforjavaobject (env, replyobj); if (reply = = null && replyobj! = null) { return jni_false; } ibinder* target = (ibinder*)//convert Binderproxy to Bpbinder Env->getintfield (obj, gbinderproxyoffsets.mobject);
...
status_t err = target->transact (code, *data, reply, flags);//call Bpbinder to communicate with the lower layer ...
Come here: The Java layer is primarily to get the native layer of bpbinder, and use it to communicate with the underlying.
Binder for Android analytics