Android—Surface,ViewRootImpl.relayoutWindow

2024-03-16 01:30

本文主要是介绍Android—Surface,ViewRootImpl.relayoutWindow,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

绘制UI会从ViewRootImpl会调用performTraversals方法开始,然后performLayout、performMeasure、performDraw。

我们跟进performDraw->draw->drawSoftware

    /*** @return true if drawing was successful, false if an error occurred*/private boolean drawSoftware(Surface surface, AttachInfo attachInfo, int xoff, int yoff,boolean scalingRequired, Rect dirty, Rect surfaceInsets) {// Draw with software renderer.final Canvas canvas;// We already have the offset of surfaceInsets in xoff, yoff and dirty region,// therefore we need to add it back when moving the dirty region.int dirtyXOffset = xoff;int dirtyYOffset = yoff;if (surfaceInsets != null) {dirtyXOffset += surfaceInsets.left;dirtyYOffset += surfaceInsets.top;}try {dirty.offset(-dirtyXOffset, -dirtyYOffset);final int left = dirty.left;final int top = dirty.top;final int right = dirty.right;final int bottom = dirty.bottom;canvas = mSurface.lockCanvas(dirty);// TODO: Do this in nativecanvas.setDensity(mDensity);} catch (Surface.OutOfResourcesException e) {handleOutOfResourcesException(e);return false;} catch (IllegalArgumentException e) {Log.e(mTag, "Could not lock surface", e);// Don't assume this is due to out of memory, it could be// something else, and if it is something else then we could// kill stuff (or ourself) for no reason.mLayoutRequested = true;    // ask wm for a new surface next time.return false;} finally {dirty.offset(dirtyXOffset, dirtyYOffset);  // Reset to the original value.}try {if (DEBUG_ORIENTATION || DEBUG_DRAW) {Log.v(mTag, "Surface " + surface + " drawing to bitmap w="+ canvas.getWidth() + ", h=" + canvas.getHeight());//canvas.drawARGB(255, 255, 0, 0);}// If this bitmap's format includes an alpha channel, we// need to clear it before drawing so that the child will// properly re-composite its drawing on a transparent// background. This automatically respects the clip/dirty region// or// If we are applying an offset, we need to clear the area// where the offset doesn't appear to avoid having garbage// left in the blank areas.if (!canvas.isOpaque() || yoff != 0 || xoff != 0) {canvas.drawColor(0, PorterDuff.Mode.CLEAR);}dirty.setEmpty();mIsAnimating = false;mView.mPrivateFlags |= View.PFLAG_DRAWN;if (DEBUG_DRAW) {Context cxt = mView.getContext();Log.i(mTag, "Drawing: package:" + cxt.getPackageName() +", metrics=" + cxt.getResources().getDisplayMetrics() +", compatibilityInfo=" + cxt.getResources().getCompatibilityInfo());}canvas.translate(-xoff, -yoff);if (mTranslator != null) {mTranslator.translateCanvas(canvas);}canvas.setScreenDensity(scalingRequired ? mNoncompatDensity : 0);mView.draw(canvas);drawAccessibilityFocusedDrawableIfNeeded(canvas);} finally {try {surface.unlockCanvasAndPost(canvas);} catch (IllegalArgumentException e) {Log.e(mTag, "Could not unlock surface", e);mLayoutRequested = true;    // ask wm for a new surface next time.//noinspection ReturnInsideFinallyBlockreturn false;}if (LOCAL_LOGV) {Log.v(mTag, "Surface " + surface + " unlockCanvasAndPost");}}return true;}

调用了mView.draw(canvas);

    @CallSuperpublic void draw(Canvas canvas) {final int privateFlags = mPrivateFlags;mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;/** Draw traversal performs several drawing steps which must be executed* in the appropriate order:**      1. Draw the background*      2. If necessary, save the canvas' layers to prepare for fading*      3. Draw view's content*      4. Draw children*      5. If necessary, draw the fading edges and restore layers*      6. Draw decorations (scrollbars for instance)*/// Step 1, draw the background, if neededint saveCount;drawBackground(canvas);// skip step 2 & 5 if possible (common case)final int viewFlags = mViewFlags;boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;if (!verticalEdges && !horizontalEdges) {// Step 3, draw the contentonDraw(canvas);// Step 4, draw the childrendispatchDraw(canvas);drawAutofilledHighlight(canvas);// Overlay is part of the content and draws beneath Foregroundif (mOverlay != null && !mOverlay.isEmpty()) {mOverlay.getOverlayView().dispatchDraw(canvas);}// Step 6, draw decorations (foreground, scrollbars)onDrawForeground(canvas);// Step 7, draw the default focus highlightdrawDefaultFocusHighlight(canvas);if (debugDraw()) {debugDrawFocus(canvas);}// we're done...return;}

可以看到mView.draw(canvas)就是具体的draw实体了,所有的视图都是作用在这个画布上。那么canvas是哪里来的呢?

回到上面可以看到

canvas = mSurface.lockCanvas(dirty);

在ViewRoot构造时,会创建一个Surface,它使用无参构造函数,这时候他还只是空的实体,代码如下所示:

 private final Surface mSurface = new Surface();

 在performTraversals方法中,有四个重要的方法:

relayoutResult = relayoutWindow(params, viewVisibility, insetsPending);
performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
performLayout(lp, mWidth, mHeight);
performDraw();

 我们知道performMeasure、performLayout、performDraw就是去测量视图宽高,布局,绘制。

这里主要分析relayoutWindow方法:

frameworks\base\core\java\android\view\ViewRootImpl.java

    private int relayoutWindow(WindowManager.LayoutParams params, int viewVisibility,boolean insetsPending) throws RemoteException {.....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, frameNumber,mTmpFrame, mPendingOverscanInsets, mPendingContentInsets, mPendingVisibleInsets,mPendingStableInsets, mPendingOutsets, mPendingBackDropFrame, mPendingDisplayCutout,mPendingMergedConfiguration, mSurfaceControl, mTempInsets);if (mSurfaceControl.isValid()) {mSurface.copyFrom(mSurfaceControl);} else {destroySurface();}....}
  1.  mWindowSession.relayout(...);
  2.  mSurface.copyFrom(mSurfaceControl);

我们先看mSurface.copyFrom(mSurfaceControl);

frameworks\base\core\java\android\view\Surface.java

    public void copyFrom(SurfaceControl other) {....long surfaceControlPtr = other.mNativeObject;long newNativeObject = nativeGetFromSurfaceControl(mNativeObject, surfaceControlPtr);....}

frameworks\base\core\jni\android_view_Surface.cpp 

static jlong nativeGetFromSurfaceControl(JNIEnv* env, jclass clazz,jlong nativeObject,jlong surfaceControlNativeObj) {Surface* self(reinterpret_cast<Surface *>(nativeObject));sp<SurfaceControl> ctrl(reinterpret_cast<SurfaceControl *>(surfaceControlNativeObj));// If the underlying IGBP's are the same, we don't need to do anything.if (self != nullptr &&IInterface::asBinder(self->getIGraphicBufferProducer()) ==IInterface::asBinder(ctrl->getIGraphicBufferProducer())) {return nativeObject;}sp<Surface> surface(ctrl->getSurface());if (surface != NULL) {surface->incStrong(&sRefBaseOwner);}return reinterpret_cast<jlong>(surface.get());
}

frameworks\native\libs\gui\SurfaceControl.cpp 

sp<Surface> SurfaceControl::getSurface() const
{Mutex::Autolock _l(mLock);if (mSurfaceData == nullptr) {return generateSurfaceLocked();}return mSurfaceData;
}sp<Surface> SurfaceControl::generateSurfaceLocked() const
{// This surface is always consumed by SurfaceFlinger, so the// producerControlledByApp value doesn't matter; using false.mSurfaceData = new Surface(mGraphicBufferProducer, false);return mSurfaceData;
}

Surface.copyFrom方法可以简单理解为从SurfaceControl对象中获取Surface。

接着分析mWindowSession.relayout(...);

先找一下mWindowSession是哪里初始化的:

IWindowSession mWindowSession = WindowManagerGlobal.getWindowSession();

frameworks\base\core\java\android\view\WindowManagerGlobal.java

    public static IWindowSession getWindowSession() {synchronized (WindowManagerGlobal.class) {if (sWindowSession == null) {try {// Emulate the legacy behavior.  The global instance of InputMethodManager// was instantiated here.// TODO(b/116157766): Remove this hack after cleaning up @UnsupportedAppUsageInputMethodManager.ensureDefaultInstanceForDefaultDisplayIfNecessary();IWindowManager windowManager = getWindowManagerService();sWindowSession = windowManager.openSession(new IWindowSessionCallback.Stub() {@Overridepublic void onAnimatorScaleChanged(float scale) {ValueAnimator.setDurationScale(scale);}});} catch (RemoteException e) {throw e.rethrowFromSystemServer();}}return sWindowSession;}}public static IWindowManager getWindowManagerService() {synchronized (WindowManagerGlobal.class) {if (sWindowManagerService == null) {sWindowManagerService = IWindowManager.Stub.asInterface(ServiceManager.getService("window"));try {if (sWindowManagerService != null) {ValueAnimator.setDurationScale(sWindowManagerService.getCurrentAnimatorScale());}} catch (RemoteException e) {throw e.rethrowFromSystemServer();}}return sWindowManagerService;}}

mWindowSession = WindowManagerGlobal.getWindowSession();中先获取了WMS,然后调用WMS的openSession获取的mWindowSession对象

frameworks\base\services\core\java\com\android\server\wm\WindowManagerService.java

    @Overridepublic IWindowSession openSession(IWindowSessionCallback callback) {return new Session(this, callback);}

所以mWindowSession是一个Session对象。

从这里我们可以知道ViewRootImpl是通过Session对象来与WMS进行通信的。

知道了他具体是什么对象,我们就能够分析他的relayout了

frameworks\base\services\core\java\com\android\server\wm\Session.java

    public int relayout(IWindow window, int seq, WindowManager.LayoutParams attrs,int requestedWidth, int requestedHeight, int viewFlags, int flags, long frameNumber,Rect outFrame, Rect outOverscanInsets, Rect outContentInsets, Rect outVisibleInsets,Rect outStableInsets, Rect outsets, Rect outBackdropFrame,DisplayCutout.ParcelableWrapper cutout, MergedConfiguration mergedConfiguration,SurfaceControl outSurfaceControl, InsetsState outInsetsState) {int res = mService.relayoutWindow(this, window, seq, attrs,requestedWidth, requestedHeight, viewFlags, flags, frameNumber,outFrame, outOverscanInsets, outContentInsets, outVisibleInsets,outStableInsets, outsets, outBackdropFrame, cutout,mergedConfiguration, outSurfaceControl, outInsetsState);return res;}

这里的mService是WMS。

frameworks\base\services\core\java\com\android\server\wm\WindowManagerService.java

    public int relayoutWindow(Session session, IWindow client,....) {....synchronized (mGlobalLock) {....if (shouldRelayout) {Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "relayoutWindow: viewVisibility_1");result = win.relayoutVisibleWindow(result, attrChanges);try {result = createSurfaceControl(outSurfaceControl, result, win, winAnimator);} catch (Exception e) {....}} else {....}....return result;}private int createSurfaceControl(SurfaceControl outSurfaceControl, int result, WindowState win,WindowStateAnimator winAnimator) {if (!win.mHasSurface) {result |= RELAYOUT_RES_SURFACE_CHANGED;}WindowSurfaceController surfaceController;try {Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "createSurfaceControl");surfaceController = winAnimator.createSurfaceLocked(win.mAttrs.type, win.mOwnerUid);} finally {Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);}if (surfaceController != null) {surfaceController.getSurfaceControl(outSurfaceControl);if (SHOW_TRANSACTIONS) Slog.i(TAG_WM, "  OUT SURFACE " + outSurfaceControl + ": copied");} else {// For some reason there isn't a surface.  Clear the// caller's object so they see the same state.Slog.w(TAG_WM, "Failed to create surface control for " + win);outSurfaceControl.release();}return result;}
  1. surfaceController = winAnimator.createSurfaceLocked(win.mAttrs.type, win.mOwnerUid);
  2. surfaceController.getSurfaceControl(outSurfaceControl);

我们先看surfaceController.getSurfaceControl(outSurfaceControl);

frameworks\base\services\core\java\com\android\server\wm\WindowSurfaceController.java

    void getSurfaceControl(SurfaceControl outSurfaceControl) {outSurfaceControl.copyFrom(mSurfaceControl);}

outSurfaceControl就是复制mSurfaceControl的值,而mSurfaceControl就是在上一步创建的。

先创建了surfaceController,然后再调surfaceController的getSurfaceControl给outSurfaceControl赋值。

接下来只要分析surfaceController是怎么生成的,就能够知道

ViewRootImpl的relayoutWindow方法中,mSurface.copyFrom(mSurfaceControl)的mSurfaceControl是哪个,就知道了mSurface是从哪来的。

frameworks\base\services\core\java\com\android\server\wm\WindowStateAnimator.java

    WindowSurfaceController createSurfaceLocked(int windowType, int ownerUid) {final WindowState w = mWin;...mSurfaceController = new WindowSurfaceController(mSession.mSurfaceSession,attrs.getTitle().toString(), width, height, format, flags, this,windowType, ownerUid);mSurfaceController.setColorSpaceAgnostic((attrs.privateFlags& WindowManager.LayoutParams.PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC) != 0);setOffsetPositionForStackResize(false);mSurfaceFormat = format;w.setHasSurface(true);....return mSurfaceController;}

frameworks\base\services\core\java\com\android\server\wm\WindowSurfaceController.java

    public WindowSurfaceController(SurfaceSession s, String name, int w, int h, int format,int flags, WindowStateAnimator animator, int windowType, int ownerUid) {mAnimator = animator;mSurfaceW = w;mSurfaceH = h;title = name;mService = animator.mService;final WindowState win = animator.mWin;mWindowType = windowType;mWindowSession = win.mSession;Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "new SurfaceControl");final SurfaceControl.Builder b = win.makeSurface().setParent(win.getSurfaceControl()).setName(name).setBufferSize(w, h).setFormat(format).setFlags(flags).setMetadata(METADATA_WINDOW_TYPE, windowType).setMetadata(METADATA_OWNER_UID, ownerUid);mSurfaceControl = b.build();Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);}

WindowSurfaceController的构造函数里面采用建造者模式创建了mSurfaceControl。

frameworks\base\core\java\android\view\SurfaceControl.java 

    public SurfaceControl build() {if (mWidth < 0 || mHeight < 0) {throw new IllegalStateException("width and height must be positive or unset");}if ((mWidth > 0 || mHeight > 0) && (isColorLayerSet() || isContainerLayerSet())) {throw new IllegalStateException("Only buffer layers can set a valid buffer size.");}return new SurfaceControl(mSession, mName, mWidth, mHeight, mFormat, mFlags, mParent, mMetadata);}private SurfaceControl(SurfaceSession session, String name, int w, int h, int format, int flags,SurfaceControl parent, SparseIntArray metadata)throws OutOfResourcesException, IllegalArgumentException {....mNativeObject = nativeCreate(session, name, w, h, format, flags,parent != null ? parent.mNativeObject : 0, metaParcel);....}

这里的nativeCreate是本地方法,继续跟下去

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, jlong parentObject,jobject metadataParcel) {ScopedUtfChars name(env, nameStr);sp<SurfaceComposerClient> client;if (sessionObj != NULL) {client = android_view_SurfaceSession_getClient(env, sessionObj);} else {client = SurfaceComposerClient::getDefault();}....sp<SurfaceControl> surface;status_t err = client->createSurfaceChecked(String8(name.c_str()), w, h, format, &surface, flags, parent, std::move(metadata));if (err == NAME_NOT_FOUND) {jniThrowException(env, "java/lang/IllegalArgumentException", NULL);return 0;} else if (err != NO_ERROR) {jniThrowException(env, OutOfResourcesException, NULL);return 0;}surface->incStrong((void *)nativeCreate);return reinterpret_cast<jlong>(surface.get());
}

frameworks\native\libs\gui\SurfaceComposerClient.cpp

status_t SurfaceComposerClient::createSurfaceChecked(const String8& name, uint32_t w, uint32_t h,PixelFormat format,sp<SurfaceControl>* outSurface, uint32_t flags,SurfaceControl* parent,LayerMetadata metadata) {....err = mClient->createSurface(name, w, h, format, flags, parentHandle, std::move(metadata),&handle, &gbp);ALOGE_IF(err, "SurfaceComposerClient::createSurface error %s", strerror(-err));if (err == NO_ERROR) {*outSurface = new SurfaceControl(this, handle, gbp, true /* owned */);}....return err;
}
  1. mClient->createSurface(....)
  2. *outSurface = new SurfaceControl(this, handle, gbp, true /* owned */) 

这个mClient是ISurfaceComposerClient对象,目前我们还不知道具体是什么,怎么来的,先放着后面分析。

所以在winAnimator.createSurfaceLocked中去new WindowSurfaceController对象,WindowSurfaceController对象的构造方法中会调用SurfaceControl的本地方法nativeCreate去本地创建一个SurfaceControl返回来。

回到ViewRootImpl的relayoutWindow

    private int relayoutWindow(WindowManager.LayoutParams params, int viewVisibility,boolean insetsPending) throws RemoteException {.....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, frameNumber,mTmpFrame, mPendingOverscanInsets, mPendingContentInsets, mPendingVisibleInsets,mPendingStableInsets, mPendingOutsets, mPendingBackDropFrame, mPendingDisplayCutout,mPendingMergedConfiguration, mSurfaceControl, mTempInsets);if (mSurfaceControl.isValid()) {mSurface.copyFrom(mSurfaceControl);} else {destroySurface();}....}

所以mSurface来自于WindowSurfaceController构造函数中实例化的mSurfaceControl对象,mSurfaceControl对象来自nativeCreate创建的SurfaceControl。

所以在performTraversals中performMeasure、performLayout、performDraw之前,ViewRootImpl会先调用relayoutWindow去创建SurfaceControl,然后从SurfaceControl中获取Surface。但是在创建SurfaceControl之前,还调用了mClient->createSurface(....)。

Surface我们知道怎么来的了,还有个遗留问题就是mClient->createSurface(....)的mClinet是怎么来的。到setView方法

frameworks\base\core\java\android\view\ViewRootImpl.java:

    public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {synchronized (this) {if (mView == null) {....requestLayout();try {res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,getHostVisibility(), mDisplay.getDisplayId(), mTmpFrame,mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,mAttachInfo.mOutsets, mAttachInfo.mDisplayCutout, mInputChannel,mTempInsets);setFrame(mTmpFrame);}....}}

requestLayout会去执行performTraversals

我们主要分析mWindowSession.addToDisplay

frameworks\base\services\core\java\com\android\server\wm\Session.java

    public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs,int viewVisibility, int displayId, Rect outFrame, Rect outContentInsets,Rect outStableInsets, Rect outOutsets,DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel,InsetsState outInsetsState) {return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId, outFrame,outContentInsets, outStableInsets, outOutsets, outDisplayCutout, outInputChannel,outInsetsState);}

frameworks\base\services\core\java\com\android\server\wm\WindowManagerService.java

    public int addWindow(Session session, IWindow client, int seq,LayoutParams attrs, int viewVisibility, int displayId, Rect outFrame,Rect outContentInsets, Rect outStableInsets, Rect outOutsets,DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel,InsetsState outInsetsState) {....synchronized (mGlobalLock) {....final WindowState win = new WindowState(this, session, client, token, parentWindow,appOp[0], seq, attrs, viewVisibility, session.mUid,session.mCanAddInternalSystemWindow);....win.attach();....}    return res;}

addWindow方法内容很多,我们只看重点,这里创建了WindowState对象然后调用了attach方法。

frameworks\base\services\core\java\com\android\server\wm\WindowState.java

    void attach() {mSession.windowAddedLocked(mAttrs.packageName);}

又回到了Session

frameworks\base\services\core\java\com\android\server\wm\Session.java

    void windowAddedLocked(String packageName) {mPackageName = packageName;mRelayoutTag = "relayoutWindow: " + mPackageName;if (mSurfaceSession == null) {mSurfaceSession = new SurfaceSession();mService.mSessions.add(this);if (mLastReportedAnimatorScale != mService.getCurrentAnimatorScale()) {mService.dispatchNewAnimatorScaleLocked(this);}}mNumWindow++;}

在Session里面创建了SurfaceSession,这里的Session是mWindowSession,用来和WMS通信的。现在又多了个SurfaceSession。

frameworks\base\core\java\android\view\SurfaceSession.java:

    public SurfaceSession() {mNativeClient = nativeCreate();}

这里又有一个nativeCreate,我们前面见过在SufaceControl里

frameworks\base\core\java\android\view\SurfaceControl.java

    private SurfaceControl(SurfaceSession session, String name, int w, int h, int format, int flags,SurfaceControl parent, SparseIntArray metadata)throws OutOfResourcesException, IllegalArgumentException {....mNativeObject = nativeCreate(session, name, w, h, format, flags,parent != null ? parent.mNativeObject : 0, metaParcel);....}

注意这两个不是同一个函数,我们找到SurfaceSession对应Native层的方法

frameworks\base\core\jni\android_view_SurfaceSession.cpp

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

SurfaceSession里面创建了SurfaceComposerClient,SurfaceComposerClient是一个重要的对象。

incStrong是RefBase的方法,里面会去调用onFirstRef

frameworks\native\libs\gui\SurfaceComposerClient.cpp

void SurfaceComposerClient::onFirstRef() {sp<ISurfaceComposer> sf(ComposerService::getComposerService());if (sf != nullptr && mStatus == NO_INIT) {sp<ISurfaceComposerClient> conn;conn = sf->createConnection();if (conn != nullptr) {mClient = conn;mStatus = NO_ERROR;}}
}
  1. ComposerService::getComposerService()
  2. mClient = conn = sf->createConnection()
sp<ISurfaceComposer> ComposerService::getComposerService() {ComposerService& instance = ComposerService::getInstance();Mutex::Autolock _l(instance.mLock);if (instance.mComposerService == NULL) {ComposerService::getInstance().connectLocked();assert(instance.mComposerService != NULL);ALOGD("ComposerService reconnected");}return instance.mComposerService;
}void ComposerService::connectLocked() {const String16 name("SurfaceFlinger");//按名称查找服务while (getService(name, &mComposerService) != NO_ERROR) {usleep(250000);}....
}template<typename INTERFACE>
status_t getService(const String16& name, sp<INTERFACE>* outService)
{const sp<IServiceManager> sm = defaultServiceManager();//服务管理者if (sm != NULL) {//获取SurfaceFlinger的IBinder,并强转为ISurfaceComposer*outService = interface_cast<INTERFACE>(sm->getService(name));if ((*outService) != NULL) return NO_ERROR;}return NAME_NOT_FOUND;
}

所以ComposerService::getComposerService()就是去获取名为SurfaceFlinger的服务,

这里获取到的是服务代理类是BpSurfaceComposer,为什么是BpSurfaceComposer呢?

class SurfaceFlinger : public BnSurfaceComposer

可以看到 SurfaceFlinger是BnSurfaceComposer的子类。

接下来看mClient = conn = sf->createConnection()

frameworks\native\libs\gui\ISurfaceComposer.cpp

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

这里就是Binder通信了,传到BnSurfaceComposer再到SurfaceFlinger的具体方法。

我们直接看SurfaceFlinger的createConnection

frameworks\native\services\surfaceflinger\SurfaceFlinger.cpp

sp<ISurfaceComposerClient> SurfaceFlinger::createConnection() {return initClient(new Client(this));
}Client::Client(const sp<SurfaceFlinger>& flinger): mFlinger(flinger)
{
}static sp<ISurfaceComposerClient> initClient(const sp<Client>& client) {status_t err = client->initCheck();if (err == NO_ERROR) {return client;}return nullptr;
}

捋一下,所以SurfaceSession通过本地方法nativeCreate,创建了SurfaceComposerClient对象,SurfaceComposerClient在初始化onFirstRef的时候会通过SurfaceFlinger服务获取Client对象给自己的mClient复制。

回到之前SurfaceComposerClient类的createSurfaceChecked方法中的mClient->createSurface(....)

frameworks\native\libs\gui\SurfaceComposerClient.cpp

status_t SurfaceComposerClient::createSurfaceChecked(const String8& name, uint32_t w, uint32_t h,PixelFormat format,sp<SurfaceControl>* outSurface, uint32_t flags,SurfaceControl* parent,LayerMetadata metadata) {....err = mClient->createSurface(name, w, h, format, flags, parentHandle, std::move(metadata),&handle, &gbp);ALOGE_IF(err, "SurfaceComposerClient::createSurface error %s", strerror(-err));if (err == NO_ERROR) {*outSurface = new SurfaceControl(this, handle, gbp, true /* owned */);}....return err;
}

发现这个mClient就是Client:BnSurfaceComposerClient对象。

接下来我们就能分析createSurface了

frameworks\native\services\surfaceflinger\Client.cpp

status_t Client::createSurface(const String8& name, uint32_t w, uint32_t h, PixelFormat format,uint32_t flags, const sp<IBinder>& parentHandle,LayerMetadata metadata, sp<IBinder>* handle,sp<IGraphicBufferProducer>* gbp) {// We rely on createLayer to check permissions.return mFlinger->createLayer(name, this, w, h, format, flags, std::move(metadata), handle, gbp,parentHandle);
}

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,LayerMetadata metadata, sp<IBinder>* handle,sp<IGraphicBufferProducer>* gbp,const sp<IBinder>& parentHandle,const sp<Layer>& parentLayer) {....switch (flags & ISurfaceComposerClient::eFXSurfaceMask) {case ISurfaceComposerClient::eFXSurfaceBufferQueue:result = createBufferQueueLayer(client, uniqueName, w, h, flags, std::move(metadata),format, handle, gbp, &layer);break;case ISurfaceComposerClient::eFXSurfaceBufferState:result = createBufferStateLayer(client, uniqueName, w, h, flags, std::move(metadata),handle, &layer);break;case ISurfaceComposerClient::eFXSurfaceColor:// check if buffer size is set for color layer.if (w > 0 || h > 0) {ALOGE("createLayer() failed, w or h cannot be set for color layer (w=%d, h=%d)",int(w), int(h));return BAD_VALUE;}result = createColorLayer(client, uniqueName, w, h, flags, std::move(metadata), handle,&layer);break;case ISurfaceComposerClient::eFXSurfaceContainer:// check if buffer size is set for container layer.if (w > 0 || h > 0) {ALOGE("createLayer() failed, w or h cannot be set for container layer (w=%d, h=%d)",int(w), int(h));return BAD_VALUE;}result = createContainerLayer(client, uniqueName, w, h, flags, std::move(metadata),handle, &layer);break;default:result = BAD_VALUE;break;}....return result;
}

这里有很多Layer,我们只看第一个

frameworks\native\services\surfaceflinger\SurfaceFlinger.cpp

status_t SurfaceFlinger::createBufferQueueLayer(const sp<Client>& client, const String8& name,uint32_t w, uint32_t h, uint32_t flags,LayerMetadata metadata, PixelFormat& format,sp<IBinder>* handle,sp<IGraphicBufferProducer>* gbp,sp<Layer>* outLayer) {....sp<BufferQueueLayer> layer = getFactory().createBufferQueueLayer(LayerCreationArgs(this, client, name, w, h, flags, std::move(metadata)));status_t err = layer->setDefaultBufferProperties(w, h, format);if (err == NO_ERROR) {*handle = layer->getHandle();*gbp = layer->getProducer();*outLayer = layer;}return err;
}

frameworks\native\services\surfaceflinger\SurfaceFlingerFactory.cpp

        sp<BufferQueueLayer> createBufferQueueLayer(const LayerCreationArgs& args) override {return new BufferQueueLayer(args);}

 BufferQueueLayer里面重写了onFirstRef方法

frameworks\native\services\surfaceflinger\BufferQueueLayer.cpp

BufferQueueLayer::BufferQueueLayer(const LayerCreationArgs& args) : BufferLayer(args) {}void BufferQueueLayer::onFirstRef() {BufferLayer::onFirstRef();// Creates a custom BufferQueue for SurfaceFlingerConsumer to usesp<IGraphicBufferProducer> producer;sp<IGraphicBufferConsumer> consumer;BufferQueue::createBufferQueue(&producer, &consumer, true);mProducer = new MonitoredProducer(producer, mFlinger, this);{// Grab the SF state lock during this since it's the only safe way to access RenderEngineMutex::Autolock lock(mFlinger->mStateLock);mConsumer =new BufferLayerConsumer(consumer, mFlinger->getRenderEngine(), mTextureName, this);}mConsumer->setConsumerUsageBits(getEffectiveUsage(0));mConsumer->setContentsChangedListener(this);mConsumer->setName(mName);// BufferQueueCore::mMaxDequeuedBufferCount is default to 1if (!mFlinger->isLayerTripleBufferingDisabled()) {mProducer->setMaxDequeuedBufferCount(2);}if (const auto display = mFlinger->getDefaultDisplayDevice()) {updateTransformHint(display);}
}

frameworks\native\libs\gui\BufferQueue.cpp

void BufferQueue::createBufferQueue(sp<IGraphicBufferProducer>* outProducer,sp<IGraphicBufferConsumer>* outConsumer,bool consumerIsSurfaceFlinger) {sp<BufferQueueCore> core(new BufferQueueCore());sp<IGraphicBufferProducer> producer(new BufferQueueProducer(core, consumerIsSurfaceFlinger))sp<IGraphicBufferConsumer> consumer(new BufferQueueConsumer(core));*outProducer = producer;*outConsumer = consumer;
}
  1. 创建BufferQueueCore
  2. 创建BufferQueueProducer
  3. 创建BufferQueueConsumer

BufferQueueCore

frameworks\native\libs\gui\include\gui\BufferQueueCore.h

    BufferQueueDefs::SlotsType mSlots;// mQueue is a FIFO of queued buffers used in synchronous mode.Fifo mQueue;// mFreeSlots contains all of the slots which are FREE and do not currently// have a buffer attached.std::set<int> mFreeSlots;// mFreeBuffers contains all of the slots which are FREE and currently have// a buffer attached.std::list<int> mFreeBuffers;// mUnusedSlots contains all slots that are currently unused. They should be// free and not have a buffer attached.std::list<int> mUnusedSlots;// mActiveBuffers contains all slots which have a non-FREE buffer attached.std::set<int> mActiveBuffers;

BufferQueueCore除了持有BufferQueueProducer,BufferQueueConsumer和mSlots,还持有mQueue,mFreeSlots,mFreeBuffers等很多队列

frameworks\native\libs\gui\include\gui\BufferQueueDefs.h

namespace android {class BufferQueueCore;namespace BufferQueueDefs {typedef BufferSlot SlotsType[NUM_BUFFER_SLOTS];} // namespace BufferQueueDefs
} // namespace android

NUM_BUFFER_SLOTS是64,所以mSlots最大数是64

BufferQueueProducer

BufferQueueProducer::BufferQueueProducer(const sp<BufferQueueCore>& core,bool consumerIsSurfaceFlinger) :mCore(core),mSlots(core->mSlots),.... {}

BufferQueueProducer会持有BufferQueueCore和mSlots队列的引用。

 BufferQueueConsumer

BufferQueueConsumer::BufferQueueConsumer(const sp<BufferQueueCore>& core) :mCore(core),mSlots(core->mSlots),mConsumerName() {}

BufferQueueConsumer同样持有BufferQueueCore和mSlots队列的引用。

 总结:在performTraversals中执行performMeasure、performLayout、performDraw之前,ViewRootImpl会先调用relayoutWindow去创建SurfaceControl,然后从SurfaceControl中获取Surface。但是在创建SurfaceControl之前,还调用了在WindowState.attach中初始化创建的mClient的createSurface方法,调用Flinger服务的createLayer生成了BufferQueueLayer,一个Layer对应一个Surface,Layer持有BufferQueueCore、BufferQueueProducer和BufferQueueConsumer,并把其中的handle和gbp赋给了SurfaceControl。

这篇关于Android—Surface,ViewRootImpl.relayoutWindow的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/813889

相关文章

Android学习总结之Java和kotlin区别超详细分析

《Android学习总结之Java和kotlin区别超详细分析》Java和Kotlin都是用于Android开发的编程语言,它们各自具有独特的特点和优势,:本文主要介绍Android学习总结之Ja... 目录一、空安全机制真题 1:Kotlin 如何解决 Java 的 NullPointerExceptio

Android NDK版本迭代与FFmpeg交叉编译完全指南

《AndroidNDK版本迭代与FFmpeg交叉编译完全指南》在Android开发中,使用NDK进行原生代码开发是一项常见需求,特别是当我们需要集成FFmpeg这样的多媒体处理库时,本文将深入分析A... 目录一、android NDK版本迭代分界线二、FFmpeg交叉编译关键注意事项三、完整编译脚本示例四

Android与iOS设备MAC地址生成原理及Java实现详解

《Android与iOS设备MAC地址生成原理及Java实现详解》在无线网络通信中,MAC(MediaAccessControl)地址是设备的唯一网络标识符,本文主要介绍了Android与iOS设备M... 目录引言1. MAC地址基础1.1 MAC地址的组成1.2 MAC地址的分类2. android与I

Android 实现一个隐私弹窗功能

《Android实现一个隐私弹窗功能》:本文主要介绍Android实现一个隐私弹窗功能,本文通过实例代码给大家介绍的非常详细,感兴趣的朋友一起看看吧... 效果图如下:1. 设置同意、退出、点击用户协议、点击隐私协议的函数参数2. 《用户协议》、《隐私政策》设置成可点击的,且颜色要区分出来res/l

Android实现一键录屏功能(附源码)

《Android实现一键录屏功能(附源码)》在Android5.0及以上版本,系统提供了MediaProjectionAPI,允许应用在用户授权下录制屏幕内容并输出到视频文件,所以本文将基于此实现一个... 目录一、项目介绍二、相关技术与原理三、系统权限与用户授权四、项目架构与流程五、环境配置与依赖六、完整

Android 12解决push framework.jar无法开机的方法小结

《Android12解决pushframework.jar无法开机的方法小结》:本文主要介绍在Android12中解决pushframework.jar无法开机的方法,包括编译指令、框架层和s... 目录1. android 编译指令1.1 framework层的编译指令1.2 替换framework.ja

Android开发环境配置避坑指南

《Android开发环境配置避坑指南》本文主要介绍了Android开发环境配置过程中遇到的问题及解决方案,包括VPN注意事项、工具版本统一、Gerrit邮箱配置、Git拉取和提交代码、MergevsR... 目录网络环境:VPN 注意事项工具版本统一:android Studio & JDKGerrit的邮

Android实现定时任务的几种方式汇总(附源码)

《Android实现定时任务的几种方式汇总(附源码)》在Android应用中,定时任务(ScheduledTask)的需求几乎无处不在:从定时刷新数据、定时备份、定时推送通知,到夜间静默下载、循环执行... 目录一、项目介绍1. 背景与意义二、相关基础知识与系统约束三、方案一:Handler.postDel

Android使用ImageView.ScaleType实现图片的缩放与裁剪功能

《Android使用ImageView.ScaleType实现图片的缩放与裁剪功能》ImageView是最常用的控件之一,它用于展示各种类型的图片,为了能够根据需求调整图片的显示效果,Android提... 目录什么是 ImageView.ScaleType?FIT_XYFIT_STARTFIT_CENTE

Android实现在线预览office文档的示例详解

《Android实现在线预览office文档的示例详解》在移动端展示在线Office文档(如Word、Excel、PPT)是一项常见需求,这篇文章为大家重点介绍了两种方案的实现方法,希望对大家有一定的... 目录一、项目概述二、相关技术知识三、实现思路3.1 方案一:WebView + Office Onl