DeathRecipient & RemoteCallbackList
DeathRecipient
DeathRecipient類的作用,當Binder服務端程式掛掉了,通知給Binder客戶端程式,binder服務端程式掛掉後,kernel會呼叫binder_release函式,傳送死亡通知給繫結的Binder代理物件
public interface DeathRecipient {
public void binderDied();
}
Android系統中的使用案列
public final class ActivityManagerService {
private final boolean attachApplicationLocked(IApplicationThread thread, int pid) {
//建立IBinder.DeathRecipient子類物件
AppDeathRecipient adr = new AppDeathRecipient(app, pid, thread);
//建立binder死亡回撥
thread.asBinder().linkToDeath(adr, 0);
}
private final class AppDeathRecipient implements IBinder.DeathRecipient {
public void binderDied() {
synchronized(ActivityManagerService.this) {
appDiedLocked(mApp, mPid, mAppThread, true);
}
}
}
}
自定義服務中的使用案列
final IBinder.DeathRecipient deathRecipient = new IBinder.DeathRecipient() {
@Override
public void binderDied() {
// 伺服器程式死亡
Log.d(TAG, "binderDied");
}
};
ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, final IBinder service) {
mIMyAidlInterface = IMyAidlInterface.Stub.asInterface(service);
if (mIMyAidlInterface != null) {
new Handler().post(new Runnable() {
@Override
public void run() {
try {
//建立binder死亡回撥,當自定義服務程式掛掉後,回撥DeathRecipient的binderDied函式
mIMyAidlInterface.asBinder().linkToDeath(deathRecipient, 0);
} catch (RemoteException e) {
e.printStackTrace();
}
}
});
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
mIMyAidlInterface = null;
}
};
bindService(new Intent(this, MyService.class), connection, Context.BIND_AUTO_CREATE);
linkToDeath
Binder的實現為空實現,因為服務端程式自己掛沒有掛,自己最清楚, 不需要來註冊函式,就算linkToDeath函式能註冊,服務端程式掛掉後,linkToDeath函式也沒有機會執行了,死亡通知是為了BinderProxy物件則需要知道服務端程式是否死亡的生死情況
public class Binder implements IBinder {
public void linkToDeath(DeathRecipient recipient, int flags) {
}
public boolean unlinkToDeath(DeathRecipient recipient, int flags) {
return true;
}
}
final class BinderProxy implements IBinder {
// 向Binder驅動註冊死亡回撥
public native void linkToDeath(DeathRecipient recipient, int flags) throws RemoteException;
public native boolean unlinkToDeath(DeathRecipient recipient, int flags);
}
RemoteCallbackList
在某些場景下,Binder服務端需要回撥每一個Binder代理物件對應的回撥介面,要先確保Binder代理物件沒有死亡,才傳送,RemoteCallbackList內部是通過DeathRecipient和匿名Binder來實現的
以A,B介面來舉例,客服端先獲取A介面的Binder代理物件, 每一個客服端都建立一個實現了B介面的Binder服務物件,通過A介面,把實現了B介面的Binder服務物件傳給A,通過kernel層的轉換,A服務中最終獲取到的是B介面的代理物件
在這裡插入圖片描述,簡要關係圖如下:
public interface IInterface
{
public IBinder asBinder();
}
public class RemoteCallbackList<E extends IInterface> {
public boolean register(E callback, Object cookie) {
synchronized (mCallbacks) {
if (mKilled) {
return false;
}
// Flag unusual case that could be caused by a leak. b/36778087
logExcessiveCallbacks();
IBinder binder = callback.asBinder();
try {
Callback cb = new Callback(callback, cookie);、
// 最終也是通過linkToDeath實現
binder.linkToDeath(cb, 0);
mCallbacks.put(binder, cb);
return true;
} catch (RemoteException e) {
return false;
}
}
}
}
// example IInterface介面為android.os.IInterface,需要Binder通訊的介面類才符合IInterface介面
public interface IMyAidlInterface extends android.os.IInterface {
public static abstract class Stub extends android.os.Binder implements com.hhtc.deathrecipient.IMyAidlInterface {
}
private static class Proxy implements com.hhtc.deathrecipient.IMyAidlInterface {
}
}