SurfaceComposerClient and SurfaceFlinger establish communication process

Keywords: supervisor

We have analyzed the process from activity creation to calling local methods to create surfacecomposerclient. In this article, we will analyze in detail how to bind SurfaceFlinger when the SurfaceComposerClient is created.

1. Apply for SurfaceComposerClient entry

[-> android_view_SurfaceSession.cpp]

static jlong nativeCreate(JNIEnv* env, jclass clazz) {
    SurfaceComposerClient* client = new SurfaceComposerClient();//See Section 2
    client->incStrong((void*)nativeCreate);
    return reinterpret_cast<jlong>(client);
}

2. SurfaceComposerClient creation

[-> SurfaceComposerClient.cpp]
The SurfaceComposerClient constructor is implemented as follows:

SurfaceComposerClient::SurfaceComposerClient()
    : mStatus(NO_INIT), mComposer(Composer::getInstance())
{
}

If it is executed for the first time, the onfirsref method will be executed

void SurfaceComposerClient::onFirstRef() {
    sp<ISurfaceComposer> sm(ComposerService::getComposerService());//See Section 2.1.
    if (sm != 0) {
        sp<ISurfaceComposerClient> conn = sm->createConnection();//See Section 2.2.
        if (conn != 0) {
            mClient = conn;
            mStatus = NO_ERROR;
        }
    }
}

2.1 get IBinder of surfacelinker

sp<ISurfaceComposer> ComposerService::getComposerService() {
    ComposerService& instance = ComposerService::getInstance();
    Mutex::Autolock _l(instance.mLock);
    if (instance.mComposerService == NULL) {
        ComposerService::getInstance().connectLocked();//See 2.1.1 Festival.
        assert(instance.mComposerService != NULL);
        ALOGD("ComposerService reconnected");
    }
    return instance.mComposerService;
}

ComposerService is a singleton mode. The function of the above method is to return directly if ComposerService has been created, or to create and execute the connectLocked method if it has not been created.

2.1.1 finding the surfacelinker service

In the process of linking, we mainly do two things:
1. Obtain corresponding services
2. Create death supervisor and bind

void ComposerService::connectLocked() {
    const String16 name("SurfaceFlinger");//Find services by name
    while (getService(name, &mComposerService) != NO_ERROR) {//See 2.1.2 Festival.
        usleep(250000);
    }
    assert(mComposerService != NULL);

    // Create the death listener.
    class DeathObserver : public IBinder::DeathRecipient {//Death surveillance
        ComposerService& mComposerService;
        virtual void binderDied(const wp<IBinder>& who) {
            ALOGW("ComposerService remote (surfaceflinger) died [%p]",
                  who.unsafe_get());
            mComposerService.composerServiceDied();
        }
     public:
        DeathObserver(ComposerService& mgr) : mComposerService(mgr) { }
    };

    mDeathObserver = new DeathObserver(*const_cast<ComposerService*>(this));//Create death surveillance object
    IInterface::asBinder(mComposerService)->linkToDeath(mDeathObserver);//Link death monitor object
}

2.1.2 link surfacelinker

getService is a template function. It uses the parameter name to find the corresponding service and converts the IBinder of the service to the output of the interface object

template<typename INTERFACE>
status_t getService(const String16& name, sp<INTERFACE>* outService)
{
    const sp<IServiceManager> sm = defaultServiceManager();//Service Manager
    if (sm != NULL) {
    //Get the IBinder of SurfaceFlinger and force to ISurfaceComposer
        *outService = interface_cast<INTERFACE>(sm->getService(name));
        if ((*outService) != NULL) return NO_ERROR;
    }
    return NAME_NOT_FOUND;
}

2.2 creating clients in surfaceFlinger by linking

Through the interface createConnection of ISurfaceComposer, the corresponding client object is created locally in surfaceFlinger, which is used to correspond with the application.

2.2.1 Binder communication

The proxy is implemented as follows:

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

The remote server is implemented as follows:

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());//Implementation of surfaceFlinger on the server side
            reply->writeStrongBinder(b);
            return NO_ERROR;
        }
        . . . . . . 
}

2.2.2 interface implementation of surfaceflinger server

At this point, the application side obtains the surfaceFlinger local client object, while the isurfacerecomposerclient is the communication bridge between the application and the client

sp<ISurfaceComposerClient> SurfaceFlinger::createConnection()
{
    sp<ISurfaceComposerClient> bclient;
    sp<Client> client(new Client(this));//Create the client corresponding to the application locally in the service
    status_t err = client->initCheck();
    if (err == NO_ERROR) {
        bclient = client;
    }
    return bclient;//Return the IBinder of the client interface
}

3, summary

To be continued......

Posted by tjg73 on Sun, 05 Apr 2020 14:06:50 -0700