When describing the relationship between Android applications and the surfaceflinger service, we mentioned that every android application with a UI needs to establish a connection with the surfaceflinger service, this connection allows you to request the surfaceflinger service to create and render a surface for it. In this article, we will take the Android system boot animation application as an example to describe how the Android Application establishes a connection with the surfaceflinger service.
The Android system boot animation is implemented by the app bootanimation, which is located in the/system/bin directory. For details, refer to the analysis of the boot screen display process of the Android system. Why do we need to use an Android system boot animation to analyze the connection process between Android applications and surfaceflinger services? First, the app bootanimation that implements the boot animation is also an Android app, but it is developed in the C ++ language. Second, the app bootanimation is related to the UI, that is, like standard Android applications developed using Java, surfaceflinger must be used to create and render your own surface, that is, boot animation. Third, because app bootanimation does not involve user input, it does not need to interact with users (touch screen, keyboard, etc ), therefore, it can reflect the relationship between Android applications and surfaceflinger services in the simplest way.
According to the analysis of the boot screen display process of the Android system, the boot animation of the Android system is mainly implemented by the bootanimation object. when constructing the bootanimation object, A surfacecomposerclient object is created internally to create a connection to the surfaceflinger service.
The constructor of the bootanimation class is implemented in the file frameworks/base/cmds/bootanimation. cpp, as shown below:
BootAnimation::BootAnimation() : Thread(false){ mSession = new SurfaceComposerClient();}
Msession is a member variable of the bootanimation class. It is a strong pointer of the surfacecomposerclient type, that is, sp <surfacecomposerclient>. For more information about the smart pointers of Android systems, see the implementation principles of the smart pointers (lightweight, strong, and weak pointers) in Android systems.
Inside the surfacecomposerclient class, there is a member variable mclient of the sp <isurfacecomposerclient> type, as shown in 1:
Figure 1 surfacecomposerclient Structure
The member variable mclient of the surfacecomposerclient class is actually a binder proxy object of the bpsurfacecomposerclient type. The binder proxy object of the bpsurfacecomposerclient type references a local binder object of the client type. As mentioned in the previous article about the relationship between the Android Application and surfaceflinger service and the learning plan, the local binder objects of the client type are created by the surfaceflinger service, and runs in the surfaceflinger service, which is used to represent a client that uses the surfaceflinger service, that is, an Android Application Related to the UI.
Because the client class and bpsurfacecomposerclient class are respectively a binder local object class and a binder proxy object class, they are implemented based on the binder inter-process communication library provided by the Android system at the application framework layer. Their implementation diagrams are shown in figure 2 and Figure 3 respectively:
Figure 2 Implementation Structure of the client class
Figure 3 structure of the bpsurfacecomposerclient class
In Figure 2 and Figure 3, many binder inter-process communication libraries are involved, which requires readers to have a certain understanding and understanding of the binder inter-process communication mechanism in the Android system. In the previous articles on the android inter-process communication (IPC) mechanism binder, we have learned about the inter-process communication mechanism of the Android system. Figure 2 and Figure 3 give us the most important information: the client class and the bpsurfacecomposerclient class both implement the binder interface with the isurfacecomposerclient type. The isurfacecomposerclient interface has two important member functions: getcontrolblock and createsurface. They are defined in the file frameworks/base/include/surfaceflinger/isurfacecomposerclient. H, as shown below:
class ISurfaceComposerClient : public IInterface{public: ...... virtual sp<IMemoryHeap> getControlBlock() const = 0; ...... /* * Requires ACCESS_SURFACE_FLINGER permission */ virtual sp<ISurface> createSurface( surface_data_t* data, int pid, const String8& name, DisplayID display, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags) = 0; ......};
The member function getcontrolblock is used to obtain an anonymous shared memory created by the surfaceflinger service to transmit UI metadata, and the member function createsurface is used to request the surfaceflinger service to create a surface. According to the previous article on the relationship between the Android Application and surfaceflinger service and the learning plan, the anonymous shared memory used to transmit UI metadata will eventually be structured as a sharedclient object, this sharedclient object exists at most one in each application process. In the next two articles, we will analyze in detail the implementation of the member functions getcontrolblock and createsurface of the isurfacecomposerclient interface. After understanding the relationships between surfacecomposerclient, client, and bpsurfacecomposerclient, we can analyze how the android boot animation app bootanimation is connected to surfaceflinger. As shown in figure 1, the surfacecomposerclient class inherits the refbase class. Therefore, when the bootanimation class creates a surfacecomposerclient object in the constructor, when this object is assigned to the smart pointer msession of the sp <surfacecomposerclient> type, onfirstref of the surfacecomposerclient class is called, the surfacecomposerclient member function onfirstref will establish a connection with the surfaceflinger service during the calling process, as shown in process 4: figure 4 connection process between the Android Application and the surfaceflinger service. Next, we will analyze each step in detail. Step 1. surfacecomposerclient: onfirstref
void SurfaceComposerClient::onFirstRef(){ sp<ISurfaceComposer> sm(getComposerService()); if (sm != 0) { sp<ISurfaceComposerClient> conn = sm->createConnection(); if (conn != 0) { mClient = conn; ...... mStatus = NO_ERROR; } }}
The surfacecomposerclient member function onfirstref is implemented in the file frameworks/base/libs/surfaceflinger_client/surfacecomposerclient. cpp.
The getcomposerservice member function of the surfacecomposerclient class is used to obtain a proxy interface of the surfaceflinger service. Its implementation is as follows:
sp<ISurfaceComposer> ComposerService::getComposerService() { return ComposerService::getInstance().mComposerService;}
The composerservice class is a singleton mode. When we call its static function getinstance for the first time, it will obtain a proxy interface of the surfaceflinger service in the constructor, and stored in its member variable mcomposerservice, as shown below:
ComposerService::ComposerService(): Singleton<ComposerService>() { const String16 name("SurfaceFlinger"); while (getService(name, &mComposerService) != NO_ERROR) { usleep(250000); } mServerCblkMemory = mComposerService->getCblk(); mServerCblk = static_cast<surface_flinger_cblk_t volatile *>( mServerCblkMemory->getBase());}
In the composerservice constructor, in addition to obtaining the proxy interface of the surfaceflinger service, getcblk is also used as a member function of the proxy interface to obtain an anonymous shared memory mservercblkmemory. This anonymous shared memory is created by the surfaceflinger service to describe information about the system display, such as the number, size, direction, and density of the display. Because this information can be described through a surface_flinger_cblk_t object, the composerservice constructor finally structured an anonymous shared memory obtained from the surfaceflinger service into a surface_flinger_cblk_t object, and stored in the member variable mservercblk of the composerservice class.
Return to the surfacecomposerclient member function onfirstref. Because the surfaceflinger Service implements the isurfacecomposer interface, we can assign the proxy interface of the surfaceflinger service obtained above to a strong pointer sm of the isurfacecomposer type, and call its member function createconnection to request the surfaceflinger service to create a connection, create a client-Type binder object and return a proxy interface conn of this binder object. After the surfacecomposerclient class obtains the conn of the client proxy interface returned by the surfaceflinger service, it is saved to its member variable mclient, in this way, the boot animation app bootanimation can be used later to request surfaceflinger to create and render the surface. Next, we will continue to analyze the implementation of the surfaceflinger service member function createconnection, so that we can understand how it creates a connection for the Android Application. Step 2. surfaceflinger: createconnection
sp<ISurfaceComposerClient> SurfaceFlinger::createConnection(){ sp<ISurfaceComposerClient> bclient; sp<Client> client(new Client(this)); status_t err = client->initCheck(); if (err == NO_ERROR) { bclient = client; } return bclient;}
The createconnection function of the surfaceflinger class is implemented in the file frameworks/base/services/surfaceflinger. in CPP, its implementation is very simple. it just creates a client-Type binder object client, and obtains an isurfacecomposerclient interface of the client. Finally, this isurfacecomposerclient interface is called a client proxy object, return to the boot animation application bootanimation.
Next, we will continue to analyze the creation process of the client object, that is, the implementation of the constructor of the client class. Step 3. New client
Client::Client(const sp<SurfaceFlinger>& flinger) : mFlinger(flinger), mNameGenerator(1){}
The client class has two member variables: mflinger and mnamegenerator. Their types are sp <surfaceflinger> and int32_t, which point to the surfaceflinger service, the latter is used to generate the name of each surface created by the surfaceflinger service for the Android Application. For example, if an android application requests surfaceflinger to create two surfaces, the first surface name is described by number 1, and the second surface is described by number 2, and so on. This article describes the relationship between the Android Application and the surfaceflinger service and the learning plan. An android application can create up to 31 surfaces. Return to the surfaceflinger class member function createconnection, which returns an isurfacecomposerclient interface pointing to a client object to the boot animation app bootanimation, the boot animation application bootanimation can encapsulate it into a binder proxy object of the bpsurfacecomposerclient type. Step 4. Return bpsurfacecomposerclient the binder proxy object encapsulation process of bpsurfacecomposerclient is implemented in createconnection of the binder proxy object class bpsurfacecomposer of surfaceflinger service, as shown below:
class BpSurfaceComposer : public BpInterface<ISurfaceComposer>{public: ...... virtual sp<ISurfaceComposerClient> createConnection() { uint32_t n; Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); remote()->transact(BnSurfaceComposer::CREATE_CONNECTION, data, &reply); return interface_cast<ISurfaceComposerClient>(reply.readStrongBinder()); } ......}
Interface_cast is a template function, which is defined in the framework/base/include/binder/iinterface. h file:
template<typename INTERFACE> inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj) { return INTERFACE::asInterface(obj); }
It can be seen from this that when the template parameter is isurfacecomposerclient, the template function interface_cast actually calls the static member function asinterface of the isurfacecomposerclient class to call a binder proxy object described by the parameter obj, A bpbinder object is encapsulated into a bpsurfacecomposerclient object.
The isurfacecomposerclient static member function asinterface is defined by the implement_meta_interface macro in the frameworks/base/libs/surfaceflinger_client/isurfacecomposerclient. cpp file, as follows:
IMPLEMENT_META_INTERFACE(SurfaceComposerClient, "android.ui.ISurfaceComposerClient");
After the implement_meta_interface macro is expanded, the implementation of the static member function asinterface of the isurfacecomposerclient class is as follows:
android::sp<ISurfaceComposerClient> ISurfaceComposerClient::asInterface(const android::sp<android::IBinder>& obj) { android::sp<ISurfaceComposerClient> intr; if (obj != NULL) { intr = static_cast<ISurfaceComposerClient*>( obj->queryLocalInterface(ISurfaceComposerClient::descriptor).get()); if (intr == NULL) { intr = new BpSurfaceComposerClient(obj); } } return intr; }
The OBJ parameter is passed in from createconnection, a member function of the bpsurfacecomposer class. It actually points to a bpbinder object. When we call querylocalinterface, a member function of the bpbinder object, a null pointer is obtained. Therefore, the static member function asinterface of the isurfacecomposerclient class encapsulates a bpbinder object pointed to by the OBJ parameter into a bpsurfacecomposerclient object and returns it to the caller.
For more details about the encapsulation process of bpsurfacecomposerclient object, refer to the previous introduction to inter-process communication (IPC) in the Android system) mechanism the server and client in the binder obtains the encapsulation process of the bpservicemanager object described in Path 1 of the Service Manager interface. So far, the boot animation app bootanimation has established a connection with the surfaceflinger service through the surfacecomposerclient class. As mentioned in the previous article about the relationship between Android applications and surfaceflinger services and the learning plan, an android application requires connection with surfaceflinger services, there is also an anonymous shared memory used to pass UI metadata, that is, a sharedclient object. Therefore, in the next article, we will continue to analyze the creation process of this anonymous shared memory, coming soon!
Lao Luo's Sina Weibo: http://weibo.com/shengyangluo. welcome to the attention!