This article is a summary of the source code. Please specify the source for the transfer. Thank you.
Welcome to your discussion. Qq: 1037701636 email: gzzaigcn2012@gmail.com
Android source code Version: 4.2.2; hardware platform A31
Step1. the previous blogs are recording the SurfaceFLinger side, that is, the so-called Server side. Next, let's take a look at how the client will transfer the image information request SF to be processed. One of the learning methods is to start with the first boot screen of android boot. Let's first look at the startup function and then look at the BootAnimation class.
Int main (int argc, char ** argv) // surfaceflinger triggers the init process to start it {# if defined (HAVE_PTHREADS) setpriority (PRIO_PROCESS, 0, ANDROID_PRIORITY_DISPLAY ); # endif char value [PROPERTY_VALUE_MAX]; property_get ("debug. sf. nobootanimation ", value," 0 "); int noBootAnimation = atoi (value); ALOGI_IF (noBootAnimation," boot animation disabled "); if (! NoBootAnimation) {sp
Proc (ProcessState: self (); ProcessState: self ()-> startThreadPool (); // the binder driver is initialized here. // create the boot animation object sp
Boot = new BootAnimation (); // initialize and call the onFirstRef of BootAnimation to start a thread boot-> playBootMusic ("/system/media/boot.wav"); IPCThreadState :: self ()-> joinThreadPool ();} return 0 ;}
We will ask where Bootanimation was started. You can refer to my previous article about how android starts and closes the process from init to boot animation (surfaceflinger startup position) it indicates that the main init process can be started only after SF is started, because bootanimation is in init. rc is the startBootAnim () in the readyToRun function that appears in the SF. // enable the animation attribute and trigger the Init process by setting the Memory attribute value:
void SurfaceFlinger::startBootAnim() { // start boot animation property_set("service.bootanim.exit", "0"); property_set("ctl.start", "bootanim");}
In the main function of BootAnimation, create a class object.
BootAnimation::BootAnimation() : Thread(false){ mSession = new SurfaceComposerClient();//SurfaceComposerClient,msession:sp
}
As you can imagine, many of the obvious things happen in the readyToRun and ThreadLoop of the Thread class thread, the new thread generally starts the run function in OnFirstRef.
In the BootAnimation constructor, we see a SurfaceComposerClient class, which is understood as an interface synthesis client. Indeed, BootAnimation will request SF as a client to complete layer rendering. So how does SCC interact with SF? Let's look at the construction process of SCC.
SurfaceComposerClient: SurfaceComposerClient (): mStatus (NO_INIT), mComposer (Composer: getInstance () {} void SurfaceComposerClient: onFirstRef () {sp
Sm (ComposerService: getComposerService (); // obtain the proxy BpSurfaceComposer if (sm! = 0) {sp
Conn = sm-> createConnection (); // create a connection to obtain the remote Client BpSurfaceComposerClient of SurfaceFlinger, corresponding to the Client if (conn! = 0) {mClient = conn; // The BpISurfaceComposerClient is saved in mclient mStatus = NO_ERROR ;}}}
Initialize a Composer class member variable when calling the constructor and use the single-column mode. Let's take a look at the operations in onFirstRef, ComposerService: getComposerService:
Sp
ComposerService: getComposerService () {ComposerService & instance = ComposerService: getInstance (); // create a ComposerService object. In the single-column mode, BpSurfaceComposer is saved to its member mComposerService Mutex :: autolock _ l (instance. mLock); if (instance. mComposerService = NULL) {ComposerService: getInstance (). connectLocked (); assert (instance. mComposerService! = NULL); ALOGD ("ComposerService reconnected");} return instance. mComposerService; // Member Code BpSurfaceComposer}
Another single-column mode of ComposerService appears internally. Let's look at its constructor:
ComposerService::ComposerService(): Singleton
() { Mutex::Autolock _l(mLock); connectLocked();}
A connectLocked function will be called:
Void ComposerService: connectLocked () {const String16 name ("SurfaceFlinger"); while (getService (name, & mComposerService )! = NO_ERROR) {// returns the proxy of surfaceflinger to mComposerService usleep (250000 );}
It is clear that getService is supposed to interact with ServiceManger, as shown below:
status_t getService(const String16& name, sp
* outService){ const sp
sm = defaultServiceManager(); if (sm != NULL) { *outService = interface_cast
(sm->getService(name)); if ((*outService) != NULL) return NO_ERROR; } return NAME_NOT_FOUND;}
Here, we can see the interaction process between the common client and SM. Here, we implement the client to request the SM to return the proxy of the SurfaceFlinger server locally. Finally, it is saved to the mCompserService variable and the object type is BpSurfaceComposer and SF (in fact, SF inherits the BnSurfaceComposer local object) to establish a Binder-based C/S communication architecture.
Well, the above Code executes so much to call the sm-> createConnection () function. This is a typical Binder communication method. You can see:
Virtual sp
CreateConnection () {uint32_t n; Parcel data, reply; data. writeInterfaceToken (ISurfaceComposer: getInterfaceDescriptor (); remote ()-> transact (BnSurfaceComposer: CREATE_CONNECTION, data, & reply); return interface_cast
(Reply. readStrongBinder (); // The returned Bpbinder is converted to SurfaceComposerClient}
The final returned result is a BpSurfaceComposerClient. Of course, the core processing is established by SF. Return to SurfaceFlinger and check the actual role of the BpSurfaceComposerClient object in SF.
SF will eventually call the createConnection () function (this process is handled by onTransact of BnSurfaceComposer, and SF inherits BnSurfaceComposer ).
Sp
SurfaceFlinger: createConnection () {sp
Bclient; sp
Client (new Client (this); // a new BnSurfaceComposerClient status_t err = client-> initCheck (); if (err = NO_ERROR) {bclient = client;} return bclient ;}
We can see that this Client is called here, and the Client must inherit BnSurfaceComposerClient Based on the Binder communication architecture. Therefore, BnSurfaceComposerClient is actually a Client class in SF,
Status_t BnSurfaceComposer: onTransact (// internal functions are completed by the inheritance class SF uint32_t code, const Parcel & data, Parcel * reply, uint32_t flags) {switch (code) {case CREATE_CONNECTION: {CHECK_INTERFACE (ISurfaceComposer, data, reply); sp
B = createConnection ()-> asBinder (); // create a Bpbinder reply-> writeStrongBinder (B); // return the handle} break of a BpBinder to the client;
Finally, it is converted to the Binder type, and a unique handle is allocated to the Binder. Finally, it is written back to the BpSurfaceComposer Client for further communication between the BpSurfaceComposerClient and the Client, the proxy of this Client is stored in the mClient member function of the SurfaceComposerClient class object.
Step2. next, let's look at readyToRun () in Bootanimation. The following function is used internally to create a local Surface.
// Create the native surface sp
Control = session ()-> createSurface (String8 ("BootAnimation"), dinfo. w, dinfo. h, PIXEL_FORMAT_RGB_565); // request surfaceflinger to create a surface
The session () function returns the previously created SurfaceComposerClient. The actual implementation of the above function is as follows:
Sp
SurfaceComposerClient: createSurface (const String8 & name, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags) {sp
Result; if (mStatus = NO_ERROR) {ISurfaceComposerClient: surface_data_t data; sp
Surface = mClient-> createSurface (& data, name, w, h, format, flags); // the corresponding volume lient on the SF side is used. BpSurface if (surface! = 0) {result = new SurfaceControl (this, surface, data); // associate the obtained surface with a SurfaceControl} return result ;}
Obviously, mClient is used to implement the interaction. Therefore, on the SF side, a Client created in the previous new Client is used to complete the interaction. Return to the onTransact function of the Client.
Status_t Client: onTransact (uint32_t code, const Parcel & data, Parcel * reply, uint32_t flags ){.... return BnSurfaceComposerClient: onTransact (code, data, reply, flags); // call createSurface of the inherited Client class}
Next, let's look:
Status_t BnSurfaceComposerClient: onTransact (uint32_t code, const Parcel & data, Parcel * reply, uint32_t flags) {switch (code) {case CREATE_SURFACE: {CHECK_INTERFACE (partition, data, reply ); surface_data_t params; String8 name = data. readString8 (); uint32_t w = data. readInt32 (); uint32_t h = data. readInt32 (); PixelFormat format = data. readInt32 (); uint32_t flags = data. readInt32 (); sp
S = createSurface (? MS, name, w, h, format, flags); // create a surface params. writeToParcel (reply); reply-> writeStrongBinder (s-> asBinder (); // The local BBinder is written to the client return NO_ERROR;} break ;......
Because BnSurfaceComposerClient is inherited by the Client, the createrSurface () function of the Client is actually called. For the implementation, see the establishment of the Surface and Layer in SurfaceFlinger in the next blog.