DeathRecipient & RemoteCallbackList

HHTC_NICE發表於2020-11-15
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.IInterfacepublic static abstract class Stub extends android.os.Binder implements com.hhtc.deathrecipient.IMyAidlInterface {
    }
    private static class Proxy implements com.hhtc.deathrecipient.IMyAidlInterface {
    }
}