In< Request layout of Android source code graphics system >In the first section, it is analyzed that the call to the relayoutWindow(...) method in the performTraversals() method of ViewRootImpl class did not go further when relocating the window. Now start with relayoutWindow(...) to sort out the subsequent process.
The relayout(...) method of Session class is finally called inside the relaywindow (...) method of ViewRootImpl class. mWindowSession points to the corresponding proxy object iwindowsession Stub. Proxy.
frameworks/base/core/java/android/view/ViewRootImpl.java
public final class ViewRootImpl implements ViewParent, View.AttachInfo.Callbacks, HardwareRenderer.HardwareDrawCallbacks { ...... // It can be accessed by any thread and must be protected with a lock. // Surface can never be reassigned or cleared (using Surface.clear()). final Surface mSurface = new Surface(); ...... private int relayoutWindow(WindowManager.LayoutParams params, int viewVisibility, boolean insetsPending) throws RemoteException { float appScale = mAttachInfo.mApplicationScale; ...... mPendingConfiguration.seq = 0; //Log.d(TAG, ">>>>>> CALLING relayout"); ...... int relayoutResult = mWindowSession.relayout( mWindow, mSeq, params, (int) (mView.getMeasuredWidth() * appScale + 0.5f), (int) (mView.getMeasuredHeight() * appScale + 0.5f), viewVisibility, insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0, mWinFrame, mPendingOverscanInsets, mPendingContentInsets, mPendingVisibleInsets, mPendingStableInsets, mPendingOutsets, mPendingConfiguration, mSurface); //Log.d(TAG, "<<<<<< BACK FROM relayout"); if (restore) { params.restore(); } ...... return relayoutResult; } ...... }
The actual work of the Session class relayout(...) method is realized by calling the WindowManagerService class relayoutWindow(...).
frameworks/base/services/core/java/com/android/server/wm/Session.java
final class Session extends IWindowSession.Stub implements IBinder.DeathRecipient { ...... public int relayout(IWindow window, int seq, WindowManager.LayoutParams attrs, int requestedWidth, int requestedHeight, int viewFlags, int flags, Rect outFrame, Rect outOverscanInsets, Rect outContentInsets, Rect outVisibleInsets, Rect outStableInsets, Rect outsets, Configuration outConfig, Surface outSurface) { if (false) Slog.d(WindowManagerService.TAG, ">>>>>> ENTERED relayout from " + Binder.getCallingPid()); int res = mService.relayoutWindow(this, window, seq, attrs, requestedWidth, requestedHeight, viewFlags, flags, outFrame, outOverscanInsets, outContentInsets, outVisibleInsets, outStableInsets, outsets, outConfig, outSurface); if (false) Slog.d(WindowManagerService.TAG, "<<<<<< EXITING relayout to " + Binder.getCallingPid()); return res; } ...... }
Now notice the outSurface argument, which is initialized in the ViewRootImpl class and passed across processes.
The Surface class represents a handle to the original buffer managed by the screen synthesizer.
frameworks/base/core/java/android/view/Surface.java
public class Surface implements Parcelable { ...... // Create an empty Surface, which will be filled later by readFromParcel(). public Surface() { } ...... }
- Call the windowForClientLocked(...) method to find the WindowState object
- Gets the WindowStateAnimator object from the WindowState object member variable mWinAnimator
- Call WindowStateAnimator class createSurfaceLocked() to get the SurfaceControl object
- Initializes the outSurface from the SurfaceControl object
frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
public class WindowManagerService extends IWindowManager.Stub implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs { ...... public int relayoutWindow(Session session, IWindow client, int seq, WindowManager.LayoutParams attrs, int requestedWidth, int requestedHeight, int viewVisibility, int flags, Rect outFrame, Rect outOverscanInsets, Rect outContentInsets, Rect outVisibleInsets, Rect outStableInsets, Rect outOutsets, Configuration outConfig, Surface outSurface) { boolean toBeDisplayed = false; boolean inTouchMode; boolean configChanged; boolean surfaceChanged = false; boolean animating; boolean hasStatusBarPermission = mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR) == PackageManager.PERMISSION_GRANTED; long origId = Binder.clearCallingIdentity(); synchronized(mWindowMap) { // The corresponding WindowState object is found WindowState win = windowForClientLocked(session, client, false); if (win == null) { return 0; } // Gets the WindowStateAnimator object from the WindowState object WindowStateAnimator winAnimator = win.mWinAnimator; if (viewVisibility != View.GONE && (win.mRequestedWidth != requestedWidth || win.mRequestedHeight != requestedHeight)) { win.mLayoutNeeded = true; win.mRequestedWidth = requestedWidth; win.mRequestedHeight = requestedHeight; } ...... // Set flag bit - whether the client requests to postpone the destruction of its Surface until it clearly indicates that it can. winAnimator.mSurfaceDestroyDeferred = (flags&WindowManagerGlobal.RELAYOUT_DEFER_SURFACE_DESTROY) != 0; ...... if (viewVisibility == View.VISIBLE && (win.mAppToken == null || !win.mAppToken.clientHidden)) { ...... try { if (!win.mHasSurface) { surfaceChanged = true; } SurfaceControl surfaceControl = winAnimator.createSurfaceLocked(); if (surfaceControl != null) { outSurface.copyFrom(surfaceControl); if (SHOW_TRANSACTIONS) Slog.i(TAG, " OUT SURFACE " + outSurface + ": copied"); } else { // For some reason there isn't a surface. Clear the // caller's object so they see the same state. outSurface.release(); } } catch (Exception e) { mInputMonitor.updateInputWindowsLw(true /*force*/); Slog.w(TAG, "Exception thrown when creating surface for client " + client + " (" + win.mAttrs.getTitle() + ")", e); Binder.restoreCallingIdentity(origId); return 0; } ...... } else { ...... outSurface.release(); if (DEBUG_VISIBILITY) Slog.i(TAG, "Releasing surface in: " + win); } ...... } ...... return (inTouchMode ? WindowManagerGlobal.RELAYOUT_RES_IN_TOUCH_MODE : 0) | (toBeDisplayed ? WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME : 0) | (surfaceChanged ? WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED : 0); } ...... }
WindowStateAnimator represents the animation and Surface operations that track a single WindowState. We focus on creating SurfaceControl objects.
frameworks/base/services/core/java/com/android/server/wm/WindowStateAnimator.java
class WindowStateAnimator { ...... SurfaceControl mSurfaceControl; ...... SurfaceControl createSurfaceLocked() { final WindowState w = mWin; if (mSurfaceControl == null) { if (DEBUG_ANIM || DEBUG_ORIENTATION) Slog.i(TAG, "createSurface " + this + ": mDrawState=DRAW_PENDING"); mDrawState = DRAW_PENDING; if (w.mAppToken != null) { if (w.mAppToken.mAppAnimator.animation == null) { w.mAppToken.allDrawn = false; w.mAppToken.deferClearAllDrawn = false; } else { // Currently in animation, please keep alldraw in its current state until the animation is completed. w.mAppToken.deferClearAllDrawn = true; } } mService.makeWindowFreezingScreenIfNeededLocked(w); int flags = SurfaceControl.HIDDEN; final WindowManager.LayoutParams attrs = w.mAttrs; if (mService.isSecureLocked(w)) { flags |= SurfaceControl.SECURE; } int width; int height; if ((attrs.flags & LayoutParams.FLAG_SCALED) != 0) { // For a scaled Surface, we always need the required size. width = w.mRequestedWidth; height = w.mRequestedHeight; } else { width = w.mCompatFrame.width(); height = w.mCompatFrame.height(); } // Something's wrong. SurfaceFlinger doesn't like this. Please try to restore it to a reasonable value if (width <= 0) { width = 1; } if (height <= 0) { height = 1; } float left = w.mFrame.left + w.mXOffset; float top = w.mFrame.top + w.mYOffset; // Adjust surface inset width += attrs.surfaceInsets.left + attrs.surfaceInsets.right; height += attrs.surfaceInsets.top + attrs.surfaceInsets.bottom; left -= attrs.surfaceInsets.left; top -= attrs.surfaceInsets.top; if (DEBUG_VISIBILITY) { Slog.v(TAG, "Creating surface in session " + mSession.mSurfaceSession + " window " + this + " w=" + width + " h=" + height + " x=" + left + " y=" + top + " format=" + attrs.format + " flags=" + flags); } // We may abort, so please initialize to the default value. mSurfaceShown = false; mSurfaceLayer = 0; mSurfaceAlpha = 0; mSurfaceX = 0; mSurfaceY = 0; w.mLastSystemDecorRect.set(0, 0, 0, 0); mHasClipRect = false; mClipRect.set(0, 0, 0, 0); mLastClipRect.set(0, 0, 0, 0); // Set the surface control with the initial size. try { mSurfaceW = width; mSurfaceH = height; final boolean isHwAccelerated = (attrs.flags & WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED) != 0; final int format = isHwAccelerated ? PixelFormat.TRANSLUCENT : attrs.format; if (!PixelFormat.formatHasAlpha(attrs.format) && attrs.surfaceInsets.left == 0 && attrs.surfaceInsets.top == 0 && attrs.surfaceInsets.right == 0 && attrs.surfaceInsets.bottom == 0) { flags |= SurfaceControl.OPAQUE; } mSurfaceFormat = format; if (DEBUG_SURFACE_TRACE) { mSurfaceControl = new SurfaceTrace( mSession.mSurfaceSession, attrs.getTitle().toString(), width, height, format, flags); } else { // Create a SurfaceControl object mSurfaceControl = new SurfaceControl( mSession.mSurfaceSession, attrs.getTitle().toString(), width, height, format, flags); } w.mHasSurface = true; if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) { Slog.i(TAG, " CREATE SURFACE " + mSurfaceControl + " IN SESSION " + mSession.mSurfaceSession + ": pid=" + mSession.mPid + " format=" + attrs.format + " flags=0x" + Integer.toHexString(flags) + " / " + this); } } catch (OutOfResourcesException e) { w.mHasSurface = false; Slog.w(TAG, "OutOfResourcesException creating surface"); mService.reclaimSomeSurfaceMemoryLocked(this, "create", true); mDrawState = NO_SURFACE; return null; } catch (Exception e) { w.mHasSurface = false; Slog.e(TAG, "Exception creating surface", e); mDrawState = NO_SURFACE; return null; } if (WindowManagerService.localLOGV) { Slog.v(TAG, "Got surface: " + mSurfaceControl + ", set left=" + w.mFrame.left + " top=" + w.mFrame.top + ", animLayer=" + mAnimLayer); } if (SHOW_LIGHT_TRANSACTIONS) { Slog.i(TAG, ">>> OPEN TRANSACTION createSurfaceLocked"); WindowManagerService.logSurface(w, "CREATE pos=(" + w.mFrame.left + "," + w.mFrame.top + ") (" + w.mCompatFrame.width() + "x" + w.mCompatFrame.height() + "), layer=" + mAnimLayer + " HIDE", null); } // Start a new transaction and apply the position and offset SurfaceControl.openTransaction(); try { mSurfaceX = left; mSurfaceY = top; try { mSurfaceControl.setPosition(left, top); mSurfaceLayer = mAnimLayer; final DisplayContent displayContent = w.getDisplayContent(); if (displayContent != null) { mSurfaceControl.setLayerStack(displayContent.getDisplay().getLayerStack()); } mSurfaceControl.setLayer(mAnimLayer); mSurfaceControl.setAlpha(0); mSurfaceShown = false; } catch (RuntimeException e) { Slog.w(TAG, "Error creating surface in " + w, e); mService.reclaimSomeSurfaceMemoryLocked(this, "create-init", true); } mLastHidden = true; } finally { // Transaction shutdown SurfaceControl.closeTransaction(); if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION createSurfaceLocked"); } if (WindowManagerService.localLOGV) Slog.v( TAG, "Created surface " + this); } return mSurfaceControl; } ...... }
Create a Surface named name.
The Surface creation flag specifies the type of Surface to create and some options, such as whether the Surface can be assumed to be opaque and whether it should be HIDDEN first. When creating a Surface, you should always set the HIDDEN flag to ensure that all Surface attributes are not made visible prematurely before they are configured.
A good practice is to first create a Surface with the specified HIDDEN flag, open a transaction, set the Surface layer, layer stack, alpha and location, call show when appropriate, and then close the transaction.
- Session surface session, cannot be null.
- Name surface name, cannot be null.
- W surface initial width.
- H initial height of surface.
- flags Surface create flags. HIDDEN should always be included in the creation tag.
nativeCreate(...) is called in the SurfaceControl constructor to create a Surface.
frameworks/base/core/java/android/view/SurfaceControl.java
public class SurfaceControl { ...... private static native long nativeCreate(SurfaceSession session, String name, int w, int h, int format, int flags) throws OutOfResourcesException; ...... public SurfaceControl(SurfaceSession session, String name, int w, int h, int format, int flags) throws OutOfResourcesException { if (session == null) { throw new IllegalArgumentException("session must not be null"); } if (name == null) { throw new IllegalArgumentException("name must not be null"); } if ((flags & SurfaceControl.HIDDEN) == 0) { Log.w(TAG, "Surfaces should always be created with the HIDDEN flag set " + "to ensure that they are not made visible prematurely before " + "all of the surface's properties have been configured. " + "Set the other properties and make the surface visible within " + "a transaction. New surface name: " + name, new Throwable()); } mName = name; mNativeObject = nativeCreate(session, name, w, h, format, flags); if (mNativeObject == 0) { throw new OutOfResourcesException( "Couldn't allocate SurfaceControl native object"); } mCloseGuard.open("release"); } ...... }
- Call android_view_SurfaceSession_getClient(...) get the SurfaceComposerClient object
- Call the createSurface(...) method of SurfaceComposerClient class to obtain the Native SurfaceControl object
- The strong reference count of the Native SurfaceControl object is incremented by one to trigger its onFirstRef(...) function call
frameworks/base/core/jni/android_view_SurfaceControl.cpp
static jlong nativeCreate(JNIEnv* env, jclass clazz, jobject sessionObj, jstring nameStr, jint w, jint h, jint format, jint flags) { ScopedUtfChars name(env, nameStr); sp<SurfaceComposerClient> client(android_view_SurfaceSession_getClient(env, sessionObj)); sp<SurfaceControl> surface = client->createSurface( String8(name.c_str()), w, h, format, flags); if (surface == NULL) { jniThrowException(env, OutOfResourcesException, NULL); return 0; } surface->incStrong((void *)nativeCreate); return reinterpret_cast<jlong>(surface.get()); }
mClient points to the BpSurfaceComposerClient object, calls its createSurface(...) method, and finally calls the createSurface(...) method in the Bn side implementation Client. Finally, the Native SurfaceControl object is created and returned.
frameworks/native/libs/gui/SurfaceComposerClient.cpp
sp<SurfaceControl> SurfaceComposerClient::createSurface( const String8& name, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags) { sp<SurfaceControl> sur; if (mStatus == NO_ERROR) { sp<IBinder> handle; sp<IGraphicBufferProducer> gbp; status_t err = mClient->createSurface(name, w, h, format, flags, &handle, &gbp); ALOGE_IF(err, "SurfaceComposerClient::createSurface error %s", strerror(-err)); if (err == NO_ERROR) { sur = new SurfaceControl(this, handle, gbp); } } return sur; }
createSurface must be called from the GL thread so that it can access the GL context.
The Client::createSurface(...) method internally defines a MessageCreateLayer class, which internally defines the handler() method, which internally calls the createLayer(...) method of the SurfaceFlinger class.
First, create a MessageCreateLayer object, then post it to the message queue for synchronous processing, and finally get the return value of the result status.
frameworks/native/services/surfaceflinger/Client.cpp
status_t Client::createSurface( const String8& name, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags, sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp) { class MessageCreateLayer : public MessageBase { SurfaceFlinger* flinger; Client* client; sp<IBinder>* handle; sp<IGraphicBufferProducer>* gbp; status_t result; const String8& name; uint32_t w, h; PixelFormat format; uint32_t flags; public: MessageCreateLayer(SurfaceFlinger* flinger, const String8& name, Client* client, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags, sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp) : flinger(flinger), client(client), handle(handle), gbp(gbp), name(name), w(w), h(h), format(format), flags(flags) { } status_t getResult() const { return result; } virtual bool handler() { result = flinger->createLayer(name, client, w, h, format, flags, handle, gbp); return true; } }; sp<MessageBase> msg = new MessageCreateLayer(mFlinger.get(), name, this, w, h, format, flags, handle, gbp); mFlinger->postMessageSync(msg); return static_cast<MessageCreateLayer*>( msg.get() )->getResult(); }
SurfaceFlinger::postMessageSync(...) is to post a message to the MessageQueue, and then call the wait() method to wait for the message to return after processing, so as to achieve the purpose of synchronization.
frameworks/native/services/surfaceflinger/SurfaceFlinger.h
class SurfaceFlinger : public BnSurfaceComposer, private IBinder::DeathRecipient, private HWComposer::EventHandler { public: ...... // post a synchronous message to the main thread status_t postMessageSync(const sp<MessageBase>& msg, nsecs_t reltime = 0, uint32_t flags = 0); ...... }
The following is the concrete implementation of the SurfaceFlinger::postMessageSync(...) method. In fact, the last two parameters are 0.
frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
status_t SurfaceFlinger::postMessageSync(const sp<MessageBase>& msg, nsecs_t reltime, uint32_t /* flags */) { status_t res = mEventQueue.postMessage(msg, reltime); if (res == NO_ERROR) { msg->wait(); } return res; }
mEventQueue is a MessageQueue type variable, which is defined under frameworks / native / services / surfacelinker /. After the above analysis, it is not difficult to leave the else branch. Notice the input parameter messageHandler, which points to the MessageCreateLayer object.
frameworks/native/services/surfaceflinger/MessageQueue.cpp
status_t MessageQueue::postMessage( const sp<MessageBase>& messageHandler, nsecs_t relTime) { const Message dummyMessage; if (relTime > 0) { mLooper->sendMessageDelayed(relTime, messageHandler, dummyMessage); } else { mLooper->sendMessage(messageHandler, dummyMessage); } return NO_ERROR; }
MessageCreateLayer class inherits MessageBase. The MessageBase class defines a member variable barrier, which is obviously used to achieve synchronization. Combined with the above analysis, the pure virtual function of handler() is implemented in the MessageCreateLayer class.
frameworks/native/services/surfaceflinger/MessageQueue.h
class MessageBase : public MessageHandler { public: MessageBase(); // return true if message has a handler virtual bool handler() = 0; // waits for the handler to be processed void wait() const { barrier.wait(); } protected: virtual ~MessageBase(); private: virtual void handleMessage(const Message& message); mutable Barrier barrier; };
Back to SurfaceFlinger, its run() method will process the message. Specifically, Looper will be called to poll and process the message in the run() method. An infinite loop inside the run() method calls the waitForEvent() method.
frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
void SurfaceFlinger::run() { do { waitForEvent(); } while (true); }
The waitForEvent() method calls the MessageQueue class waitMessage() method internally.
frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
void SurfaceFlinger::waitForEvent() { mEventQueue.waitMessage(); }
waitMessage() internally calls the Looper class pollOnce(...) to poll the message, and finally calls the MessageHandler class handleMessage(...) method to process the message.
frameworks/native/services/surfaceflinger/MessageQueue.cpp
void MessageQueue::waitMessage() { do { IPCThreadState::self()->flushCommands(); int32_t ret = mLooper->pollOnce(-1); switch (ret) { case Looper::POLL_WAKE: case Looper::POLL_CALLBACK: continue; case Looper::POLL_ERROR: ALOGE("Looper::POLL_ERROR"); case Looper::POLL_TIMEOUT: // timeout (should not happen) continue; default: // should not happen ALOGE("Looper::pollOnce() returned unknown status %d", ret); continue; } } while (true); }
Now let's look at the implementation of handleMessage(...). The handler() method is called internally, and finally the barrier is opened, so that the SurfaceFlinger::postMessageSync(...) method can return.
frameworks/native/services/surfaceflinger/MessageQueue.cpp
void MessageBase::handleMessage(const Message&) { this->handler(); barrier.open(); };
Now continue to analyze the createLayer(...) method of the SurfaceFlinger class.
- Create different layers according to different types
- Call the addClientLayer(...) method to add a layer to the Client
frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
status_t SurfaceFlinger::createLayer( const String8& name, const sp<Client>& client, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags, sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp) { //ALOGD("createLayer for (%d x %d), name=%s", w, h, name.string()); if (int32_t(w|h) < 0) { ALOGE("createLayer() failed, w or h is negative (w=%d, h=%d)", int(w), int(h)); return BAD_VALUE; } status_t result = NO_ERROR; sp<Layer> layer; switch (flags & ISurfaceComposerClient::eFXSurfaceMask) { case ISurfaceComposerClient::eFXSurfaceNormal: result = createNormalLayer(client, name, w, h, flags, format, handle, gbp, &layer); break; case ISurfaceComposerClient::eFXSurfaceDim: result = createDimLayer(client, name, w, h, flags, handle, gbp, &layer); break; default: result = BAD_VALUE; break; } if (result != NO_ERROR) { return result; } result = addClientLayer(client, *handle, *gbp, layer); if (result != NO_ERROR) { return result; } setTransactionFlags(eTransactionNeeded); return result; }
The Layer object is created in the SurfaceFlinger::createNormalLayer(...) method.
The LayerDim object is created in the SurfaceFlinger::createDimLayer(...) method.
Both handle (pointing to Binder proxy object) and gbp (pointing to GraphicBufferProducer proxy object) assignments are obtained from the layer.
frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
status_t SurfaceFlinger::createNormalLayer(const sp<Client>& client, const String8& name, uint32_t w, uint32_t h, uint32_t flags, PixelFormat& format, sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp, sp<Layer>* outLayer) { // Initialize Surface switch (format) { case PIXEL_FORMAT_TRANSPARENT: case PIXEL_FORMAT_TRANSLUCENT: format = PIXEL_FORMAT_RGBA_8888; break; case PIXEL_FORMAT_OPAQUE: format = PIXEL_FORMAT_RGBX_8888; break; } *outLayer = new Layer(this, client, name, w, h, flags); status_t err = (*outLayer)->setBuffers(w, h, format, flags); if (err == NO_ERROR) { *handle = (*outLayer)->getHandle(); *gbp = (*outLayer)->getProducer(); } ALOGE_IF(err, "createNormalLayer() failed (%s)", strerror(-err)); return err; } status_t SurfaceFlinger::createDimLayer(const sp<Client>& client, const String8& name, uint32_t w, uint32_t h, uint32_t flags, sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp, sp<Layer>* outLayer) { *outLayer = new LayerDim(this, client, name, w, h, flags); *handle = (*outLayer)->getHandle(); *gbp = (*outLayer)->getProducer(); return NO_ERROR; }
Finally, let's analyze how to call the addClientLayer(...) method to add a layer to the Client.
- Add layers to layersSortedByZ (Z-Order)
- Add gbc Binder object to mGraphicBufferProducerList
- attach layer to client
frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
status_t SurfaceFlinger::addClientLayer(const sp<Client>& client, const sp<IBinder>& handle, const sp<IGraphicBufferProducer>& gbc, const sp<Layer>& lbc) { // Add this layer to the current status list { Mutex::Autolock _l(mStateLock); if (mCurrentState.layersSortedByZ.size() >= MAX_LAYERS) { return NO_MEMORY; } mCurrentState.layersSortedByZ.add(lbc); mGraphicBufferProducerList.add(IInterface::asBinder(gbc)); } // attach this layer to the client client->attachLayer(handle, lbc); return NO_ERROR; }
The Client::attachLayer(...) method simply adds handle as key and layer as value to the vector.
frameworks/native/services/surfaceflinger/Client.cpp
void Client::attachLayer(const sp<IBinder>& handle As key,, const sp<Layer>& layer) { Mutex::Autolock _l(mLock); mLayers.add(handle, layer); }
Now go back to the analysis and create the Native SurfaceControl object. The three member variables mClient, mHandle and mGraphicBufferProducer are initialized with arguments.
frameworks/native/libs/gui/SurfaceControl.cpp
SurfaceControl::SurfaceControl( const sp<SurfaceComposerClient>& client, const sp<IBinder>& handle, const sp<IGraphicBufferProducer>& gbp) : mClient(client), mHandle(handle), mGraphicBufferProducer(gbp) { }
So far, we will continue to analyze the creation of Layer and the initialization of outSurface (call its copyFrom(...) method, and the input parameter is the SurfaceControl object).