In the above "Binder Mechanism 2 of Android system -- Service proxy object (1)", we learned the Service proxy object bpbinder at the C/C ++ layer of the process, and the underlying Processing Method of binder. In this article, we will analyze in depth the creation and use of Service proxy objects at the Java layer of the process.
C/C ++ and Java layers of the android process
In Android, most programs are developed in Java, and the underlying layer calls C/C ++ code through JNI. Such a program is divided into two levels: C/C ++ and Java. In the running state, we say they are all in one process and have the same process attributes (UID, GID, and so on ).
We have learned about the C/C ++-level objects and Principles of the binder client program in the preceding section "Binder Mechanism 2 of Android system-Service proxy object (1. Next, we will introduce how the client program creates a Service proxy by calling the underlying C/C ++ code through JNI at the Java level.
Servicemanager type and Object
I have introduced in Service Manager, one of the binder Mechanisms in Android. To obtain a Service proxy, the client must first query the service from servicemanager. This is also true at the Java level, so we first analyze the servicemanager class at the Java level.
By viewing the servicemanager source code, we found that the servicemanager type is also a singleton type. All methods are static methods,
All static methods access its iservicemanager type static variable sservicemanager, which is defined as follows:
1: private static IServiceManager sServiceManager;
Therefore, servicemanager is a proxy of the iservicemanager object. The getiservicemanager method of servicemanager is used to create and access this variable. The definition is as follows:
1: private static IServiceManager getIServiceManager() {
2: if (sServiceManager != null) {
3: return sServiceManager;
4: }
5:
6: // Find the service manager
7: sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
8: return sServiceManager;
9: }
The above Code clearly tells us that the servicemanager type is a singleton type. Now we mainly study how to create sservicemanager objects. The following code creates an iservicemanager object:
1: sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
First, let's look at the code of the getcontextobject method of the binderinternal class and find that it is the native generation.
Code (haha! At the C/C ++ level, we are familiar with it.) The corresponding code is in android_util_binder.cpp.
Android_ OS _binderinternal_getcontextobject function, the Code is as follows:
1: static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
2: {
3: sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
4: return javaObjectForIBinder(env, b);
5: }
Finally, we can see the processstate object introduced in "Binder Mechanism 2 of Android system -- Service proxy object (1)". Let's check the getcontextobject method of the processstate object. The Code is as follows:
1: sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& caller)
2: {
3: if (supportsProcesses()) {
4: return getStrongProxyForHandle(0);
5: } else {
6: return getContextObject(String16("default"), caller);
7: }
8: }
We can see that the processstate object in the current process is actually calling the getstrongproxyforhandle method to create a service proxy object-bpbinder object whose binder handle is 0, we mentioned in Service Manager, one of the binder Mechanisms in Android, that servicemanager's binder handle is a well-known handle 0. The getstrongproxyforhandle method of the processstate object has been introduced in the Binder Mechanism 2 of Android system-Service proxy object (1.
We can see that Java calls C/C ++ to create a service proxy object bpbinder. After viewing the definition of bpbinder, we find that it inherits from the ibinder interface and then
In android_util_binder.cpp, Set
C/C ++-level ibinder objects are encapsulated into Java-level ibinder objects. For more information, see
Android_ OS _binderinternal_getcontextobject method.
Now we know binderinternal. getcontextobject () and return the Service proxy object of servicemanager --
Bpbinder object. So what is the use of the static asinterface method of the servicemanagernative class? We still use code for analysis, in
In servicemanagernative. Java, the asinterface code is as follows:
1: static public IServiceManager asInterface(IBinder obj)
2: {
3: if (obj == null) {
4: return null;
5: }
6: IServiceManager in =
7: (IServiceManager)obj.queryLocalInterface(descriptor);
8: if (in != null) {
9: return in;
10: }
11:
12: return new ServiceManagerProxy(obj);
13: }
A servicemanagerproxy pair is created with the ibinder object.
For example, the servicemanagerproxy type inherits the iservicemanager interface, so the ultimate goal of the asinterface method is to use
Create an iservicemanager object.
Why create an iservicemanager object with the ibinder object? How can I directly request services in servicemanager through the servicemanager proxy object-ibinder object (bpbinder object? In the previous article "Binder Mechanism 2 of Android system-Service proxy object (1)", we briefly introduced the ibinder type. The client sends a request to the service through the transact method, the ontransact of the client is called to process client requests. Requests are differentiated by the request code. For more information, see the android manual.
If the client directly calls the ibinder interface of the servicemanager proxy object, the client must remember all request code, which is unfriendly to the client. Institute
In the servicemanagernative class, encapsulate the servicemanager proxy object-ibinder object (bpbinder object)
The servicemanagerproxy object is exposed to the client program as an iservicemanager interface, so that the iservicemanager object will be proxy
The request from the client program to the proxy object of servicemanager. In addition, it is to call the iservicemanager object method to send to servicemanager
In this way, the client program is consistent with the local function call, and the interface is very friendly. For example, our customer program needs to call the getservice method of iservicemanager.
Servicemanagerproxy provides the following code to query a service:
1: public IBinder getService(String name) throws RemoteException {
2: Parcel data = Parcel.obtain();
3: Parcel reply = Parcel.obtain();
4: data.writeInterfaceToken(IServiceManager.descriptor);
5: data.writeString(name);
6: mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);
7: IBinder binder = reply.readStrongBinder();
8: reply.recycle();
9: data.recycle();
10: return binder;
11: }
We can clearly see that the servicemanagerproxy object converts client program requests to the servicemanager proxy object-ibinder pair
Like (bpbinder object) Call. Later, we will introduce in detail how to query and obtain a system service proxy object through iservicemanager.
Now we have analyzed the creation of servicemanager's singleton object, sservicemanager. If you have any questions, check the code.
Query and obtain Service proxy objects
The client obtains the iservicemanager object by calling the static method asinterface of the servicemanager type. However, the ultimate goal is to query and obtain other services. Generally, the getservice method of iservicemanager must be called, obtain other services from servicemanager. For example:
1: IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
The above code calls the static method of servicemanager to obtain the Network Management Service proxy object. Let's take a look at how the system generates this service proxy object. Here is a brief description of the call sequence. For details about the process, see the source code.
1. Call the static servicemanager method getservice in servicemanager. java.
2. Call the servicemanagerproxy method getservice in servicemanagernative. java. The Code is as follows:
1: public IBinder getService(String name) throws RemoteException {
2: Parcel data = Parcel.obtain();
3: Parcel reply = Parcel.obtain();
4: data.writeInterfaceToken(IServiceManager.descriptor);
5: data.writeString(name);
6: mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);
7: IBinder binder = reply.readStrongBinder();
8: reply.recycle();
9: data.recycle();
10: return binder;
11: }
Please note that the ibinder transact method is a synchronous method (in this example, after servicemanager completes the request processing, it will return). We can see that after the request is called, reply is called. readstrongbinder () to read ibinder objects.
3. Check the readstrongbinder method in parcel. java. If it is found to be a native method, it will call the C/C ++ code.
4. view the android_ OS _parcel_readstrongbinder function in android_util_binder.cpp. The Code is as follows:
1: static jobject android_os_Parcel_readStrongBinder(JNIEnv* env, jobject clazz)
2: {
3: Parcel* parcel = parcelForJavaObject(env, clazz);
4: if (parcel != NULL) {
5: return javaObjectForIBinder(env, parcel->readStrongBinder());
6: }
7: return NULL;
8: }
Parcel-> readstrongbinder () generates an ibinder object.
5. Check the parcel method readstrongbinder in parcel. cpp. The Code is as follows:
1: sp<IBinder> Parcel::readStrongBinder() const
2: {
3: sp<IBinder> val;
4: unflatten_binder(ProcessState::self(), *this, &val);
5: return val;
6: }
6. Check the parcel method unflatten_binder in parcel. cpp. The Code is as follows:
1: status_t unflatten_binder(const sp<ProcessState>& proc,
2: const Parcel& in, sp<IBinder>* out)
3: {
4: const flat_binder_object* flat = in.readObject(false);
5:
6: if (flat) {
7: switch (flat->type) {
8: case BINDER_TYPE_BINDER:
9: *out = static_cast<IBinder*>(flat->cookie);
10: return finish_unflatten_binder(NULL, *flat, in);
11: case BINDER_TYPE_HANDLE:
12: *out = proc->getStrongProxyForHandle(flat->handle);
13: return finish_unflatten_binder(
14: static_cast<BpBinder*>(out->get()), *flat, in);
15: }
16: }
17: return BAD_TYPE;
18: }
Finally, we can see that the getstrongproxyforhandle method of calling our old friend processstate object will create a bpbinder object, and then the bpbinder object will be converted to an ibinder object and returned to the Java layer.
7. In order to use the service conveniently, the Java layer can encapsulate the Service proxy object-bpbinder object (ibinder object) into a client-friendly proxy object, as shown in the preceding servicemanagerproxy.
8. the user program can access the corresponding service through the proxy object.
As described above, we understand how to create and use a service proxy object on the Java layer. The Binder Mechanism of the Android system is profound and profound. In this article, many aspects are confusing. For more information, see the android source code.
References:
IPC framework analysis binder, service, service manager
Original