04 In-depth exploration of waitForService<ISurfaceComposer>

There is such a piece of code in the previous analysis of “Constructing surfaceComposerClient”

bool ComposerService::connectLocked() {
    const String16 name("SurfaceFlinger");
    mComposerService = waitForService<ISurfaceComposer>(name);
    if (mComposerService == nullptr) {
        return false; // fatal error or permission problem
    }
... ...
}

waitForService, this article will take an in-depth look at its implementation.

android12\frameworks\
ative\libs\binder\include\binder\IServiceManager.h
template<typename INTERFACE>
sp<INTERFACE> waitForService(const String16 & amp; name) {
    const sp<IServiceManager> sm = defaultServiceManager();
    return interface_cast<INTERFACE>(sm->waitForService(name));
}

android12\frameworks\
ative\libs\binder\include\binder\IInterface.h
template<typename INTERFACE>
inline sp<INTERFACE> interface_cast(const sp<IBinder> & amp; obj)
{
    return INTERFACE::asInterface(obj);
}

If you can’t tell, replace the template class with ISurfaceComposer

sp<ISurfaceComposer> waitForService(const String16 & amp; name) {
    const sp<IServiceManager> sm = defaultServiceManager();
    return interface_cast<ISurfaceComposer>(sm->waitForService(name));
}

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

Quickly find the implementation of ISurfaceComposer’s asInterface.

I searched for a long time but couldn’t find it.,,,, I searched for a long time and finally found it. It turned out that it was hidden with a macro.

android12\frameworks\
ative\libs\gui\include\gui\ISurfaceComposer.h
class ISurfaceComposer: public IInterface {
public:
    DECLARE_META_INTERFACE(SurfaceComposer)
... ...
}

After expanding the macro, it looks like this

#define DECLARE_META_INTERFACE(INTERFACE) \
public: \
    static const ::android::String16 descriptor; \
    static ::android::sp<ISurfaceComposer> asInterface( \
            const ::android::sp<::android::IBinder> & amp; obj); \
    virtual const ::android::String16 & amp; getInterfaceDescriptor() const; \
    ISurfaceComposer(); \
    virtual ~ISurfaceComposer(); \
    static bool setDefaultImpl(std::unique_ptr<ISurfaceComposer> impl); \
    static const std::unique_ptr<ISurfaceComposer> & amp; getDefaultImpl(); \
private:\
    static std::unique_ptr<ISurfaceComposer> default_impl; \
public: \

It looks like it’s just a statement here, and then keep looking. . . . . .

Finally found it in android12\frameworks\
ative\libs\gui\ISurfaceComposer.cpp

IMPLEMENT_META_INTERFACE(SurfaceComposer, “android.ui.ISurfaceComposer”);

After expanding the macro, you can see the following implementation:

 ::android::sp<ISurfaceComposer> ISurfaceComposer::asInterface( \
            const ::android::sp<::android::IBinder> & amp; obj) \
    {\
        ::android::sp<ISurfaceComposer> intr; \
        if (obj != nullptr) { \
            intr = ::android::sp<ISurfaceComposer>::cast( \
                obj->queryLocalInterface(ISurfaceComposer::descriptor)); \
            if (intr == nullptr) { \
                intr = ::android::sp<BpSurfaceComposer>::make(obj); \
            } \
        } \
        return intr; \
    } \

Oh, the point is, it turns out that using interface_cast will use the binder pointer to create a BpSurfaceComposer.

Let’s take a look at BpSurfaceComposer

BpSurfaceComposer implements many interfaces to interact with BnSurfaceComposer. Take createConnection as an example

android12\frameworks\
ative\libs\gui\ISurfaceComposer.cpp
class BpSurfaceComposer : public BpInterface<ISurfaceComposer>
{
public:
    explicit BpSurfaceComposer(const sp<IBinder> & amp; impl)
        : BpInterface<ISurfaceComposer>(impl)
    {
    }

    virtual ~BpSurfaceComposer();

    virtual sp<ISurfaceComposerClient> createConnection()
    {
        Parcel data, reply;
        data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
        remote()->transact(BnSurfaceComposer::CREATE_CONNECTION, data, & amp;reply);
        return interface_cast<ISurfaceComposerClient>(reply.readStrongBinder());
    }
    ... ...
}

In “Constructing surfaceComposerClient” conn = sf->createConnection();

There is no detailed introduction, but here is an introduction:

conn = sf->createConnection(); BpSurfaceComposer::createConnection() will actually be called here;

Through binder, send remote call BnSurfaceComposer::CREATE_CONNECTION;

CREATE_CONNECTION will be received in BnSurfaceComposer::onTransact; and createConnection() will be executed.

status_t BnSurfaceComposer::onTransact(
    uint32_t code, const Parcel & data, Parcel* reply, uint32_t flags)
{
    switch(code) {
        case CREATE_CONNECTION: {
            CHECK_INTERFACE(ISurfaceComposer, data, reply);
            sp<IBinder> b = IInterface::asBinder(createConnection());
            reply->writeStrongBinder(b);
            return NO_ERROR;
        }
}

Because SurfaceFlinger inherits BnSurfaceComposer, SurfaceFlinger::createConnection() is called here.

class SurfaceFlinger : public BnSurfaceComposer,
                       public PriorityDumper,
                       private IBinder::DeathRecipient,
                       private HWC2::ComposerCallback,
                       private ISchedulerCallback {
... ...
}

Convert the created Client and return it through Binder.

Looking back at sp createConnection()

 virtual sp<ISurfaceComposerClient> createConnection()
    {
        Parcel data, reply;
        data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
        remote()->transact(BnSurfaceComposer::CREATE_CONNECTION, data, & amp;reply);
        return interface_cast<ISurfaceComposerClient>(reply.readStrongBinder());
    }

Use the returned binder pointer to create BpSurfaceComposerClient. This process is consistent with this analysis.

Summarize:

This article sorts out the internal mechanism of waitForService and the calling process of Bpxxx/Bnxxx. This should be done for code reuse.

With BpSurfaceComposer, various interfaces of SurfaceFlinger can be called remotely.

As shown below

Creation is not easy, welcome to like and collect.