上小節講解了Binder系統的分層,該小節我們講解Binder系統的内部機制,在上小節我們遺留了很多問題沒有接到。
1.應用程式是java編寫的,binder系統是C程式,那麼java程式是如何調用C程式的呢?
我們先來回到這個問題,即這個小節需要講解的内容:
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsICM38FdsYkRGZkRG9lcvx2bjxiNx8VZ6l2cs0TPR1kMjpXT4FkeNBDOsJGcohVYsR2MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZwpmLycTN1AzNxETMxEDNwkTMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)
從上圖我們可以看到:
TestServer首先通過addservice向service_manager注冊服務:這個時候TestServer是用戶端,service_manager為服務端。
TestClient通過getService向service_manager擷取服務:這個時候TestClient是用戶端,service_manager為服務端
TestClient使用服務,調用sayhello:這個時候TestClient為用戶端,TestServer為服務端。
下面我們檢視一下addService與getService兩個函數
打開TestServer.java:
public class TestServer {
ServiceManager.addService("hello", new HelloService());
getIServiceManager().addService(name, service, false);
sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
static public IServiceManager asInterface(IBinder obj)
return new ServiceManagerProxy(obj);
return sServiceManager;
可以知道其最後建立了一個ServiceManagerProxy,調用ServiceManagerProxy.addService(),
getService也是同樣,調用ServiceManagerProxy.getService()。
現在我們來檢視一下ServiceManagerProxy在ServiceManagerNative.cpp中:
class ServiceManagerProxy implements IServiceManager {
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);
IBinder binder = reply.readStrongBinder();
reply.recycle();
data.recycle();
return binder;
}
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);
mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);
reply.recycle();
data.recycle();
}
其都是構造資料,然後通過mRemote.transact發送資料,下面我們打開IHelloService.java:
@Override public void sayhello() throws android.os.RemoteException
mRemote.transact(Stub.TRANSACTION_sayhello, _data, _reply, 0);
@Override public int sayhello_to(java.lang.String name) throws android.os.RemoteException
mRemote.transact(Stub.TRANSACTION_sayhello_to, _data, _reply, 0);
其上兩個函數屬于IHelloService.stub.Proxy類。其最後也是使用mRemote.transac傳送資料。
下面是兩個類的繼承圖示:
ServiceManagerProxy與IHelloService.stub.Proxy都使用mRemote.transact發送資料,是以他們被統一起來了。
我們知道資料傳輸的3到要素:1.源。2.目的。3.資料。
其上的mRemote可以代表目的。
對于addSevice/getSevice其中的mRemote肯定還有handle=0這個值。mRemote
是一個java BinderProxy對象。他的mobject指向c++的一個Bpbinder對象。這個Bpbinder的mHandle=0.
對于sayhello/sayhello_to,mRemote也是一個java BinderProxy對象,他的的mbject指向一個C++的Bpbinder對象,其中的handle=1,來自于getService(“hello”)。
我們首先來看看addSevice/getSevice
addSevice/getSevice
ServiceManagerProxy中mRemote的構造(用于addSevice/getSevice),其使用0直接構造一個java BinderProxy對象。打開TestServer,可以知道其使用:
根據上面找到ServiceManager.java檔案中的addService//getSevice方法:
addService
public static void addService(String name, IBinder service) {
getIServiceManager().addService(name, service, false);
getSevice
public static IBinder getService(String name) {
return getIServiceManager().getService(name);
return sServiceManager = sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
我們先不分析asInterface方法,分析其參數。
可以知道,這是一個C或者C++實作的函數,其最終得到一個java Binderproxy對象,其成員mOject=new Bpbinder(0)在源碼搜尋getContextObject,可以在android_util_Binder.cpp檔案中找到:
static const JNINativeMethod gBinderInternalMethods[] = {
/* name, signature, funcPtr */
{ "getContextObject", "()Landroid/os/IBinder;", (void*)android_os_BinderInternal_getContextObject },
{ "joinThreadPool", "()V", (void*)android_os_BinderInternal_joinThreadPool },
{ "disableBackgroundScheduling", "(Z)V", (void*)android_os_BinderInternal_disableBackgroundScheduling },
{ "setMaxThreads", "(I)V", (void*)android_os_BinderInternal_setMaxThreads },
{ "handleGc", "()V", (void*)android_os_BinderInternal_handleGc }
};
可以知道其對應的函數為android_os_BinderInternal_getContextObject:
static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
{
sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
return javaObjectForIBinder(env, b);
/*使用C++的代碼,調用java某個類中的構造函數,建立一個java的對象*/
object = env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor);
env->SetLongField(object, gBinderProxyOffsets.mObject, (jlong)val.get());
return object;
}
我們在ProcessState.cpp中找到getContextObject函數:
sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
{
return getStrongProxyForHandle(0);
b = new BpBinder(handle);
到這裡我們知道其handle為0,其中的 new BpBinder(handle)通過 return javaObjectForIBinder(env, b)傳回。
現在我們分析ServiceManagerNative.asInterface(BinderInternal.getContextObject()),在ServiceManagerNative.cpp中:
public abstract class ServiceManagerNative extends Binder implements IServiceManager
/*obj為一個BinderProxy對象*/
return new ServiceManagerProxy(obj);
我們進入ServiceManagerProxy的構造函數:
class ServiceManagerProxy implements IServiceManager {
public ServiceManagerProxy(IBinder remote) {
mRemote = remote; //其為上面建立的BinderProxy對象中的mObject指向new BpBinder
}
下面我們看看sayhello/sayhello_to中的mRemote是怎麼構造的:
sayhello/sayhello_to
打開TestClient.java:
public static void main(String args[])
IBinder binder = ServiceManager.getService("hello");
IHelloService svr = IHelloService.Stub.asInterface(binder);
我們先分析簡單的asInterface在IHelloService檔案中:
public static IHelloService asInterface(android.os.IBinder obj)
return new IHelloService.Stub.Proxy(obj);
/*IHelloService.Stub.Proxy的構造函數*/
mRemote = remote;
其中的obj為ServiceManager.getService得到的IBinder binder。
下面分析IBinder binder = ServiceManager.getService(“hello”),我們可以猜測其傳回值就是一個java BinderProxy對象,其中的mOject = new BpBinder(handel)。進入ServiceManagerNative.java:
public IBinder getService(String name) throws RemoteException {
IBinder binder = reply.readStrongBinder();
//parcel.java
return nativeReadStrongBinder(mNativePtr);
看到nativeReadStrongBinder,我們可以知道其是通過c++實作,在源碼中搜尋nativeReadStrongBinder,可以在android_os_Parcel.cpp中找到他的實作函數
static jobject android_os_Parcel_readStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr)
{
/*把java parcel對象轉化為c++parcel對象*/
/*client程式向service_manege發出getService請求,
得到一個回複reply,他裡面含有一個flat_binder_object,
他被封裝成一個C++的parcel對象*/
Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
if (parcel != NULL) {
return javaObjectForIBinder(env, parcel->readStrongBinder());
}
return NULL;
}
可以看到其中調用了javaObjectForIBinder,他會建立一個java BinderProxy對象,其中的mObject = new BpBinder(handle)對象