Binder in Android are used for Inter Process Communication. In Android code base, interface_cast and asBinder function are used at multiple places in context of Binder. This article tries to explain the interpretation of these API.

interface_cast

Let’s analyze it based on the following ICameraClient example:

// https://android.googlesource.com/platform/frameworks/av/+/refs/heads/master/camera/ICamera.cpp
sp<ICameraClient> cameraClient = interface_cast<ICameraClient>(data.readStrongBinder());

Look at the implementation of interface_cast, the code is in IInterface.h

// Code snippet: https://android.googlesource.com/platform/frameworks/native/+/refs/heads/master/libs/binder/include/binder/IInterface.h
/**
 * If this is a local object and the descriptor matches, this will return the
 * actual local object which is implementing the interface. Otherwise, this will
 * return a proxy to the interface without checking the interface descriptor.
 * This means that subsequent calls may fail with BAD_TYPE.
 */
template<typename INTERFACE>
inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
{
    return INTERFACE::asInterface(obj);
}

This is a template function, which is expanded as:

inline sp<ICameraClient> interface_cast(const sp<IBinder>& obj)
{
    return ICameraClient ::asInterface(obj);
}

asInterface

Lets look at the implementation of asInterface of ICameraClient. ICameraClient.h and ICameraClient.cpp have only the following two definitions:

// https://android.googlesource.com/platform/frameworks/av/+/refs/heads/master/camera/ICameraClient.cpp
IMPLEMENT_META_INTERFACE(CameraClient, "android.hardware.ICameraClient");

// https://android.googlesource.com/platform/frameworks/av/+/refs/heads/master/camera/include/camera/android/hardware/ICameraClient.h
DECLARE_META_INTERFACE(CameraClient);

The DECLARE_META_INTERFACE and IMPLEMENT_META_INTERFACE functions are the macro definitions of its parent class IInterface. Below illustrate the code snippet of the same.

//Declare the asInterface function
#define DECLARE_META_INTERFACE(INTERFACE)
    static const android::String16 descriptor;
   //Declare the asInterface function
    static android::sp<I##INTERFACE> asInterface( 
            const android::sp<android::IBinder>& obj);
    virtual const android::String16& getInterfaceDescriptor() const;
    I##INTERFACE();
    virtual ~I##INTERFACE();

//Implement asInterface function
#define IMPLEMENT_META_INTERFACE(INTERFACE, NAME)
    const android::String16 I##INTERFACE::descriptor(NAME); 
    const android::String16& 
            I##INTERFACE::getInterfaceDescriptor() const { 
        return I##INTERFACE::descriptor; 
    }                                               
    android::sp<I##INTERFACE> I##INTERFACE::asInterface(
            const android::sp<android::IBinder>& obj)
    {
        android::sp<I##INTERFACE> intr; 
        if (obj != NULL) {
            intr = static_cast<I##INTERFACE*>(
                obj->queryLocalInterface( 
                        I##INTERFACE::descriptor).get()); 
            if (intr == NULL) {
                intr = new Bp##INTERFACE(obj);//Expansion is intr = new BpServiceManager(obj);
            }
        }
        return intr;
    }
    I##INTERFACE::I##INTERFACE() {}
    I##INTERFACE::~I##INTERFACE() {}

When used with the above example, above will expand to

// Expand to
#define DECLARE_META_INTERFACE(CameraClient)
   //Add a descriptor
    static const android::String16 descriptor;
   //Declare the asInterface function
    static android::sp<ICameraClient> asInterface( 
            const android::sp<android::IBinder>& obj);
   //Get the descriptor function
    virtual const android::String16& getInterfaceDescriptor() const;
   //Constructor and folding function
    ICameraClient();
    virtual ~ICameraClient();



// Expand to
#define IMPLEMENT_META_INTERFACE(CameraClient, "android.hardware.ICameraClient")
   //Define the descriptor of ICameraClient as "android.hardware.ICameraClient"
    const android::String16 ICameraClient ::descriptor("android.hardware.ICameraClient"); 
   //Get the descriptor "android.hardware.ICameraClient"
    const android::String16& 
            ICameraClient ::getInterfaceDescriptor() const { 
        return ICameraClient ::descriptor; 
    }                        
   //Implement asInterface function
    android::sp<ICameraClient> ICameraClient::asInterface(
            const android::sp<android::IBinder>& obj)
    {
        android::sp<ICameraClient> intr; 
        if (obj != NULL) {
            intr = static_cast<ICameraClient*>(
               //queryLocalInterface is defined in IBinder and returns NULL by default, but in BBinder's subclass BnInterface, this method is overloaded and returns this, while BpBinder is not overloaded, using the default implementation of IBinder, returning NULL
                obj->queryLocalInterface( 
                        ICameraClient::descriptor).get()); 
            if (intr == NULL) {
               //Build INTERFACE's Bp-side proxy object
                intr = new BpCameraClient(obj);
            }
        }
        return intr;
    }
    ICameraClient::ICameraClient() {}
    ICameraClient::~ICameraClient() {}

To summarize, if the parameter obj of interface_cast is BnInterface, it returns itself. If the parameter obj is BpInterface, then a new Bp proxy object is returned. Here we use the ICameraClient example to explain, it returns BpCameraClient.

asBinder

Below code shows the snippet of asBinder API.

// https://android.googlesource.com/platform/frameworks/native/+/refs/heads/master/libs/binder/IInterface.cpp
// static
sp<IBinder> IInterface::asBinder(const IInterface* iface)
{
    if (iface == nullptr) return nullptr;
    return sp<IBinder>::fromExisting(const_cast<IInterface*>(iface)->onAsBinder());
}
// static
sp<IBinder> IInterface::asBinder(const sp<IInterface>& iface)
{
    if (iface == nullptr) return nullptr;
    return sp<IBinder>::fromExisting(iface->onAsBinder());
}

BnInterface

The onAsBinder method of BnInterface returns itself directly, because BnInterface inherits from BBinder, and BBinder inherits from IBinder.

// https://android.googlesource.com/platform/frameworks/native/+/refs/heads/master/libs/binder/include/binder/IInterface.h
template<typename INTERFACE>
class BnInterface : public INTERFACE, public BBinder
{
public:
    virtual sp<IInterface>      queryLocalInterface(const String16& _descriptor);
    virtual const String16&     getInterfaceDescriptor() const;
protected:
    typedef INTERFACE           BaseInterface;
    virtual IBinder*            onAsBinder();
};

BpInterface

The onAsBinder method of BpInterface calls the remote() method and returns.

// https://android.googlesource.com/platform/frameworks/native/+/refs/heads/master/libs/binder/include/binder/IInterface.h
template<typename INTERFACE>
class BpInterface : public INTERFACE, public BpRefBase
{
public:
    explicit                    BpInterface(const sp<IBinder>& remote);
protected:
    typedef INTERFACE           BaseInterface;
    virtual IBinder*            onAsBinder();
};


// Implementation of remote in BpRefBase
inline  IBinder*        remote()                { return mRemote; }

The mRemote variable passes the remote variable to its parent class BpRefBase when creating the BpInterface object.

// https://android.googlesource.com/platform/frameworks/native/+/refs/heads/master/libs/binder/Binder.cpp
BpRefBase::BpRefBase(const sp<IBinder>& o)
    : mRemote(o.get()), mRefs(nullptr), mState(0)
{
    extendObjectLifetime(OBJECT_LIFETIME_WEAK);
    if (mRemote) {
        mRemote->incStrong(this);           // Removed on first IncStrong().
        mRefs = mRemote->createWeak(this);  // Held for our entire lifetime.
    }
}