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 kotlin语言实现删除文件的解决方案

《Androidkotlin语言实现删除文件的解决方案》:本文主要介绍Androidkotlin语言实现删除文件的解决方案,在项目开发过程中,尤其是需要跨平台协作的项目,那么删除用户指定的文件的... 目录一、前言二、适用环境三、模板内容1.权限申请2.Activity中的模板一、前言在项目开发过程中,尤

Android数据库Room的实际使用过程总结

《Android数据库Room的实际使用过程总结》这篇文章主要给大家介绍了关于Android数据库Room的实际使用过程,详细介绍了如何创建实体类、数据访问对象(DAO)和数据库抽象类,需要的朋友可以... 目录前言一、Room的基本使用1.项目配置2.创建实体类(Entity)3.创建数据访问对象(DAO

Android WebView的加载超时处理方案

《AndroidWebView的加载超时处理方案》在Android开发中,WebView是一个常用的组件,用于在应用中嵌入网页,然而,当网络状况不佳或页面加载过慢时,用户可能会遇到加载超时的问题,本... 目录引言一、WebView加载超时的原因二、加载超时处理方案1. 使用Handler和Timer进行超

Android实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo

Android平台播放RTSP流的几种方案探究(VLC VS ExoPlayer VS SmartPlayer)

技术背景 好多开发者需要遴选Android平台RTSP直播播放器的时候,不知道如何选的好,本文针对常用的方案,做个大概的说明: 1. 使用VLC for Android VLC Media Player(VLC多媒体播放器),最初命名为VideoLAN客户端,是VideoLAN品牌产品,是VideoLAN计划的多媒体播放器。它支持众多音频与视频解码器及文件格式,并支持DVD影音光盘,VCD影

android-opencv-jni

//------------------start opencv--------------------@Override public void onResume(){ super.onResume(); //通过OpenCV引擎服务加载并初始化OpenCV类库,所谓OpenCV引擎服务即是 //OpenCV_2.4.3.2_Manager_2.4_*.apk程序包,存

从状态管理到性能优化:全面解析 Android Compose

文章目录 引言一、Android Compose基本概念1.1 什么是Android Compose?1.2 Compose的优势1.3 如何在项目中使用Compose 二、Compose中的状态管理2.1 状态管理的重要性2.2 Compose中的状态和数据流2.3 使用State和MutableState处理状态2.4 通过ViewModel进行状态管理 三、Compose中的列表和滚动

Android 10.0 mtk平板camera2横屏预览旋转90度横屏拍照图片旋转90度功能实现

1.前言 在10.0的系统rom定制化开发中,在进行一些平板等默认横屏的设备开发的过程中,需要在进入camera2的 时候,默认预览图像也是需要横屏显示的,在上一篇已经实现了横屏预览功能,然后发现横屏预览后,拍照保存的图片 依然是竖屏的,所以说同样需要将图片也保存为横屏图标了,所以就需要看下mtk的camera2的相关横屏保存图片功能, 如何实现实现横屏保存图片功能 如图所示: 2.mtk

android应用中res目录说明

Android应用的res目录是一个特殊的项目,该项目里存放了Android应用所用的全部资源,包括图片、字符串、颜色、尺寸、样式等,类似于web开发中的public目录,js、css、image、style。。。。 Android按照约定,将不同的资源放在不同的文件夹中,这样可以方便的让AAPT(即Android Asset Packaging Tool , 在SDK的build-tools目

Android fill_parent、match_parent、wrap_content三者的作用及区别

这三个属性都是用来适应视图的水平或者垂直大小,以视图的内容或尺寸为基础的布局,比精确的指定视图的范围更加方便。 1、fill_parent 设置一个视图的布局为fill_parent将强制性的使视图扩展至它父元素的大小 2、match_parent 和fill_parent一样,从字面上的意思match_parent更贴切一些,于是从2.2开始,两个属性都可以使用,但2.3版本以后的建议使