https://www.bilibili.com/video/BV1zb4y187MW/
一、aidl文件
下面是自己寫的一個aidl文件
package android.os;
interface IHelloService
{
void setVal(int val);
int getVal();
}
注意,這是一個aidl文件倘屹,編譯后會生成一個IHelloService.java圆雁。我們來看一下這個文件的內(nèi)容隱藏著什么奧秘,可以這么神奇地支持進(jìn)程間通信。
在java中有一個aidl文件,讓我們省去了很多工作,其實下了下面這段將aidl文件展開其實很c++很像斑响。
/*
This file is auto-generated. DO NOT MODIFY.
-
Original file: frameworks/base/core/java/android/os/IHelloService.aidl
/
package android.os;
public interface IHelloService extends android.os.IInterface
{
/* Local-side IPC implementation stub class. /
public static abstract class Stub extends android.os.Binder implements android.os.IHelloService//相當(dāng)于是一個Server端菱属,需要一個子類來繼續(xù)繼承它,完成接口的實現(xiàn)
{
private static final java.lang.String DESCRIPTOR = "android.os.IHelloService";
/* Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}/** * Cast an IBinder object into an android.os.IHelloService interface, * generating a proxy if needed. */ public static android.os.IHelloService asInterface(android.os.IBinder obj)//和c++類似舰罚,如果在client端才去new一個proxy { if ((obj==null)) { return null; } android.os.IInterface iin = (android.os.IInterface)obj.queryLocalInterface(DESCRIPTOR); if (((iin!=null)&&(iin instanceof android.os.IHelloService))) { return ((android.os.IHelloService)iin); } return new android.os.IHelloService.Stub.Proxy(obj); } public android.os.IBinder asBinder() { return this; } @Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException { switch (code) { case INTERFACE_TRANSACTION: { reply.writeString(DESCRIPTOR); return true; } case TRANSACTION_setVal: { data.enforceInterface(DESCRIPTOR); int _arg0; _arg0 = data.readInt(); this.setVal(_arg0); reply.writeNoException(); return true; } case TRANSACTION_getVal: { data.enforceInterface(DESCRIPTOR); int _result = this.getVal(); reply.writeNoException(); reply.writeInt(_result); return true; } } return super.onTransact(code, data, reply, flags); } private static class Proxy implements android.os.IHelloService//這個內(nèi)部類纽门,相當(dāng)于一個client端和C++類似 { private android.os.IBinder mRemote; Proxy(android.os.IBinder remote) { mRemote = remote; } public android.os.IBinder asBinder() { return mRemote; } public java.lang.String getInterfaceDescriptor() { return DESCRIPTOR; } public void setVal(int val) throws android.os.RemoteException { android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); try { _data.writeInterfaceToken(DESCRIPTOR); _data.writeInt(val); mRemote.transact(Stub.TRANSACTION_setVal, _data, _reply, 0); _reply.readException(); } finally { _reply.recycle(); _data.recycle(); } } public int getVal() throws android.os.RemoteException { android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); int _result; try { _data.writeInterfaceToken(DESCRIPTOR); mRemote.transact(Stub.TRANSACTION_getVal, _data, _reply, 0); _reply.readException(); _result = _reply.readInt(); } finally { _reply.recycle(); _data.recycle(); } return _result; } } static final int TRANSACTION_setVal = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0); static final int TRANSACTION_getVal = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
}
public void setVal(int val) throws android.os.RemoteException;
public int getVal() throws android.os.RemoteException;
}
這里我們可以看到IHelloService.aidl這個文件編譯后的真面目,原來就是根據(jù)IHelloService接口的定義生成相應(yīng)的Stub和Proxy類沸停,這個就是我們熟悉的Binder機(jī)制的內(nèi)容了膜毁,即實現(xiàn)這個HelloService的Server必須繼續(xù)于這里的IHelloService.Stub類,而這個HelloService的遠(yuǎn)程接口就是這里的IHelloService.Stub.Proxy對象獲得的IHelloService接口愤钾。接下來的內(nèi)容瘟滨,我們就可以看到IHelloService.Stub和IHelloService.Stub.Proxy是怎么創(chuàng)建或者使用的。
二. HelloService的啟動過程
在討論HelloService的啟動過程之前能颁,我們先來看一下實現(xiàn)HelloService接口的Server是怎么定義的杂瘸。
我們在frameworks/base/services/java/com/android/server目錄下新增了一個HelloService.java文件:
package com.android.server;
import android.content.Context;
import android.os.IHelloService;
import android.util.Slog;
public class HelloService extends IHelloService.Stub {//實現(xiàn)aidl文件解析后,里面的內(nèi)部類
private static final String TAG = "HelloService";
HelloService() {
init_native();
}
public void setVal(int val) {
setVal_native(val);
}
public int getVal() {
return getVal_native();
}
private static native boolean init_native();
private static native void setVal_native(int val);
private static native int getVal_native();
}
這里伙菊,我們可以看到败玉,HelloService繼續(xù)了IHelloService.Stub類,它通過本地方法調(diào)用實現(xiàn)了getVal和setVal兩個函數(shù)镜硕。
有了HelloService這個Server類后运翼,下一步就是考慮怎么樣把它啟動起來了。在frameworks/base/services/java/com/android/server/SystemServer.java文件中兴枯,定義了SystemServer類血淌。SystemServer對象是在系統(tǒng)啟動的時候創(chuàng)建的,它被創(chuàng)建的時候會啟動一個線程來創(chuàng)建HelloService财剖,并且把它添加到Service Manager中去悠夯。
我們來看一下這部份的代碼:
class ServerThread extends Thread {
......
@Override
public void run() {
......
Looper.prepare();
......
try {
Slog.i(TAG, "Hello Service");
ServiceManager.addService("hello", new HelloService());//加入serviceManager中
} catch (Throwable e) {
Slog.e(TAG, "Failure starting Hello Service", e);
}
......
Looper.loop();
......
}
}
......
public class SystemServer
{
......
/**
* This method is called from Zygote to initialize the system. This will cause the native
* services (SurfaceFlinger, AudioFlinger, etc..) to be started. After that it will call back
* up into init2() to start the Android services.
*/
native public static void init1(String[] args);
......
public static final void init2() {
Slog.i(TAG, "Entered the Android system server!");
Thread thr = new ServerThread();
thr.setName("android.server.ServerThread");
thr.start();
}
......
}
三. Client獲取HelloService的Java遠(yuǎn)程接口的過程
我們看看它是如何借助Service Manager這個Java遠(yuǎn)程接口來獲得HelloService的遠(yuǎn)程接口的。在Hello這個Activity的onCreate函數(shù)躺坟,通過IServiceManager.getService函數(shù)來獲得HelloService的遠(yuǎn)程接口:
public class Hello extends Activity implements OnClickListener {
......
private IHelloService helloService = null;
......
@Override
public void onCreate(Bundle savedInstanceState) {
helloService = IHelloService.Stub.asInterface(
ServiceManager.getService("hello"));//調(diào)用自定義的helloservice沦补,不過需要自己asInterface轉(zhuǎn)成自己的接口
}
......
}
至于,java調(diào)用c++的那些JNI就不分析了咪橙。
四夕膀、在c層service中實現(xiàn)java層回調(diào)
還有有時候我們自己寫了一個c層的binder service,然后通過java調(diào)用service中代碼美侦,然后其實又需要在c層中注冊回調(diào)产舞。這個時候可以在c層service的注冊接口中增加binder參數(shù),然后在java中實現(xiàn)aidl文件音榜,再把binder參數(shù)通過service調(diào)用傳入c層service,到時候就可以在c層service中回調(diào)java代碼了捧弃。