java編寫binder服務實例
https://www.cnblogs.com/winfu/p/7521372.html
1.編寫AIDL 文件
IHelloService.aidl:
/** {@hide} */
interface IHelloService
{
void sayhello();
int sayhello_to(String name);
}
1.把 IHelloService.aidl 放入 frameworks/base/core/java/android/os
2.修改 frameworks/base/Android.mk 添加一行
core/java/android/os/IVibratorService.aidl \
+ core/java/android/os/IHelloService.aidl \
3. 編譯/framework/base
4.系統自動生成IHelloService.java
public interface IHelloService extends android.os.IInterface
{
public static abstract class Stub extends android.os.Binder implements IHelloService{
private static final java.lang.String DESCRIPTOR = "IHelloService";
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
public static IHelloService asInterface(android.os.IBinder obj)
{ ... ...
return new IHelloService.Stub.Proxy(obj);
}
@Override public android.os.IBinder asBinder()
@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) ...
{
switch (code)
{
case INTERFACE_TRANSACTION:
case TRANSACTION_sayhello:
case TRANSACTION_sayhello_to:
}
}
private static class Proxy implements IHelloService
static final int TRANSACTION_sayhello = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_sayhello_to = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
}
public void sayhello() throws android.os.RemoteException;
public int sayhello_to(java.lang.String name) throws android.os.RemoteException;
}
IHelloService.java 的結構爲:
1.名字爲IHelloService 的interface:
2.IHelloService 這個interface 中有一個繼承Binder 的抽象類stub
IHelloService.aidl 中已經定義好的service 中的幾個函數的虛函數
public interface IHelloService extends android.os.IInterface
{
public static abstract class Stub extends android.os.Binder implements IHelloService ...
public void sayhello() throws android.os.RemoteException;
public int sayhello_to(java.lang.String name) throws android.os.RemoteException;
}
2.HelloService.java
import android.util.Slog;
public class HelloService extends IHelloService.Stub {
private static final String TAG = "HelloService";
... ...
public void sayhello() throws android.os.RemoteException {
... ...
}
public int sayhello_to(java.lang.String name) throws android.os.RemoteException {
... ...
}
}
1. HelloService.java 繼承 IHelloService.Stub 這個內部類;
2. HelloService.java 中複寫 之前在IHelloService.aidl 中定義好的函數
3.Client端代碼
import android.util.Slog;
import android.os.ServiceManager;
import android.os.IBinder;
public class TestClient {
public static void main(String args[])
{
if (args[0].equals("hello"))
{
/* 1. getService */
IBinder binder = ServiceManager.getService("hello");
IHelloService svr = IHelloService.Stub.asInterface(binder);
svr.sayhello();
int cnt = svr.sayhello_to(args[1]);
}
}
}
總結:
1.自己先寫一個IHelloService.aidl ,系統編譯後生成IHelloService.java
2.IHelloService.java是一個接口,其中定義了一個繼承了binder 的抽象的 內部類stub,stub中實現了在IHelloService.aidl中定義方法的實現:將需要傳輸的數據打包爲Parcel 類型,調用super.onTransact傳輸出去。
3.內部類stub中定義了一個實現了IHelloService接口的內部類proxy,proxy中實現了之前定義方法在client端的實現:初始化Parcel,調用mRemote.transact 發送出去。
4.內部類stub 中定義了一個返回 stub中內部類proxy類 的函數asInterface()
5.HelloService 繼承IHelloService.stub
6.client端通過ServiceManager.getService("hello")得到IBinder 對象,傳入到IHelloService.stub.asInterface() 這個靜態方法中獲取IHelloService對象,就可以直接調用函數了。
=========================================================================================
https://www.jianshu.com/p/adaa1a39a274
* Parcel
Parcel是一個容器,主要就是用來進行IPC通信的。
1.Parcel的獲取 :
Parcel parcle = Parcel.Obtain();
或者
new Parcel();
2.Parcel 傳入數據
parcel.writeInt(int val); // 傳入Int 型數據
parcel.writeString(String val); //傳入String 型 數據
3.Parcel 獲取數據
private PrintJobInfo(@NonNull Parcel parcel) {
.. .. ..
mLabel = parcel.readString();
mState = parcel.readInt();
.. .. ..
1. 如何確定目標binder 實體,喚醒進程/線程
binder_proc 結構體
struct binder_proc {
struct hlist_node proc_node;
struct rb_root threads;
struct rb_root nodes;
struct rb_root refs_by_desc;
struct rb_root refs_by_node;
... ...
struct list_head todo;
wait_queue_head_t wait;
... ...
};
nodes : Binder實體在內核中對應的數據結構
binder_node : 記錄進程相關的binder_proc
1.SM.addService(XXXservice) ,將XXXservice 對應的binder_ref 放入SM 的binder_ref
2.SM.getService(XXXservice),查詢SM 的binder_ref,將XXXservice 對應的binder_ref返回給client
3.client將binder_transaction事物插入到XXXservice 的binder_proc待處理隊列
2.Binder傳輸數據的大小限制
ProcessState類中,限制每次傳輸大小不超過4M
3.系統服務與bindService服務的區別
1.系統服務:通過SM.addService 添加的service,由ServiceManager 進行管理
2.BinderService:通過Activity的startService啓動,Service 只是一個封裝,主要是Binder服務實類,不是ServiceManager管理,是AMS 在管理;Activity.binderService添加的service 無法被SM.getService 獲取到;
3.BinderService是去ActivityManagerService中去查找相應的Service組件,最終會將Service內部Binder的句柄傳給Client。
4.Binder請求的同步與異步
5.Binder協議中BC_TRANSACTION與BR_TRANSACTION
BC與BR主要是標誌數據及Transaction流向;
BC_TRANSACTION從用戶空間流向內核
BR_TRANSACTION從內核流線用戶空間