android图形学之SurfaceControl和Surface的关系 五

SurfaceControl 基于android 15源码分析

前言:SurfaceControl的在构建的时候会传一个IBinder类型的参数mHandle,这个参数会一直通过native层到SF创建一个Layer(图层),在BLastBufferQueue的设计中,会持有mHandler的对象,将App的绘画的内容,设置到Layer中。至此,不入代码就是扯淡,安排。

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

performTraversals()在 performTraversals函数中relayoutWindow这就是SurfaceControl的开始之路。

java 复制代码
  private int relayoutWindow(WindowManager.LayoutParams params, int viewVisibility,
9495              boolean insetsPending) throws RemoteException {
9496          final WindowConfiguration winConfigFromAm = getConfiguration().windowConfiguration;
9497          final WindowConfiguration winConfigFromWm =
9498                  mLastReportedMergedConfiguration.getMergedConfiguration().windowConfiguration;
9499          final WindowConfiguration winConfig = getCompatWindowConfiguration();
9500          final int measuredWidth = mMeasuredWidth;
9501          final int measuredHeight = mMeasuredHeight;
9502          final boolean relayoutAsync;
9503          if ((mViewFrameInfo.flags & FrameInfo.FLAG_WINDOW_VISIBILITY_CHANGED) == 0
9504                  && mWindowAttributes.type != TYPE_APPLICATION_STARTING
9505                  && mSyncSeqId <= mLastSyncSeqId
9506                  && winConfigFromAm.diff(winConfigFromWm, false /* compareUndefined */) == 0) {
9507              final InsetsState state = mInsetsController.getState();
9508              final Rect displayCutoutSafe = mTempRect;
9509              state.getDisplayCutoutSafe(displayCutoutSafe);
9510              mWindowLayout.computeFrames(mWindowAttributes.forRotation(winConfig.getRotation()),
9511                      state, displayCutoutSafe, winConfig.getBounds(), winConfig.getWindowingMode(),
9512                      measuredWidth, measuredHeight, mInsetsController.getRequestedVisibleTypes(),
9513                      1f /* compatScale */, mTmpFrames);
9514              mWinFrameInScreen.set(mTmpFrames.frame);
9515              if (mTranslator != null) {
9516                  mTranslator.translateRectInAppWindowToScreen(mWinFrameInScreen);
9517              }
9518  
9519              // If the position and the size of the frame are both changed, it will trigger a BLAST
9520              // sync, and we still need to call relayout to obtain the syncSeqId. Otherwise, we just
9521              // need to send attributes via relayoutAsync.
9522              final Rect oldFrame = mLastLayoutFrame;
9523              final Rect newFrame = mTmpFrames.frame;
9524              final boolean positionChanged =
9525                      newFrame.top != oldFrame.top || newFrame.left != oldFrame.left;
9526              final boolean sizeChanged =
9527                      newFrame.width() != oldFrame.width() || newFrame.height() != oldFrame.height();
9528              relayoutAsync = !positionChanged || !sizeChanged;
9529          } else {
9530              relayoutAsync = false;
9531          }
9532  
9533          float appScale = mAttachInfo.mApplicationScale;
9534          boolean restore = false;
9535          if (params != null && mTranslator != null) {
9536              restore = true;
9537              params.backup();
9538              mTranslator.translateWindowLayout(params);
9539          }
9540  
9541          if (params != null) {
9542              if (DBG) Log.d(mTag, "WindowLayout in layoutWindow:" + params);
9543  
9544              if (mOrigWindowType != params.type) {
9545                  // For compatibility with old apps, don't crash here.
9546                  if (mTargetSdkVersion < Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
9547                      Slog.w(mTag, "Window type can not be changed after "
9548                              + "the window is added; ignoring change of " + mView);
9549                      params.type = mOrigWindowType;
9550                  }
9551              }
9552          }
9553  
9554          final int requestedWidth = (int) (measuredWidth * appScale + 0.5f);
9555          final int requestedHeight = (int) (measuredHeight * appScale + 0.5f);
9556          int relayoutResult = 0;
9557          mRelayoutSeq++;
9558          if (relayoutAsync) {
9559              mWindowSession.relayoutAsync(mWindow, params,
9560                      requestedWidth, requestedHeight, viewVisibility,
9561                      insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0, mRelayoutSeq,
9562                      mLastSyncSeqId);
9563          } else { 
                        /**同步布局的情况下,系统的程序会走到这里,调用Session的relayout函数
                        最后的一个参数mRelayoutResult,这个参数封装的java层的SurfaceControl的对象,这个对象是new出来的小白
                         private final WindowRelayoutResult mRelayoutResult = new WindowRelayoutResult(
                          mTmpFrames, mPendingMergedConfiguration, mSurfaceControl, mTempInsets, mTempControls);
                        */
9564              relayoutResult = mWindowSession.relayout(mWindow, params,
9565                      requestedWidth, requestedHeight, viewVisibility,
9566                      insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0,
9567                      mRelayoutSeq, mLastSyncSeqId, mRelayoutResult);
9568              mRelayoutRequested = true;
9569  
9570              onClientWindowFramesChanged(mTmpFrames);
9571  
9572              if (mPendingActivityWindowInfo != null) {
9573                  final ActivityWindowInfo outInfo = mRelayoutResult.activityWindowInfo;
9574                  if (outInfo != null) {
9575                      mPendingActivityWindowInfo.set(outInfo);
9576                  }
9577              }
9578              final int maybeSyncSeqId = mRelayoutResult.syncSeqId;
9579              if (maybeSyncSeqId > 0) {
9580                  mSyncSeqId = maybeSyncSeqId;
9581              }
9582  
9583              mWinFrameInScreen.set(mTmpFrames.frame);
9584              if (mTranslator != null) {
9585                  mTranslator.translateRectInScreenToAppWindow(mTmpFrames.frame);
9586                  mTranslator.translateRectInScreenToAppWindow(mTmpFrames.displayFrame);
9587                  mTranslator.translateRectInScreenToAppWindow(mTmpFrames.attachedFrame);
9588              }
9589              mInvCompatScale = 1f / mTmpFrames.compatScale;
9590              CompatibilityInfo.applyOverrideIfNeeded(mPendingMergedConfiguration);
9591              handleInsetsControlChanged(mTempInsets, mTempControls);
9592  
9593              mPendingAlwaysConsumeSystemBars =
9594                      (relayoutResult & RELAYOUT_RES_CONSUME_ALWAYS_SYSTEM_BARS) != 0;
9595          }
9596  
9597          final int transformHint = SurfaceControl.rotationToBufferTransform(
9598                  (mDisplay.getInstallOrientation() + mDisplay.getRotation()) % 4);
9599          final boolean transformHintChanged = transformHint != mPreviousTransformHint;
9600          mPreviousTransformHint = transformHint;
9601          mSurfaceControl.setTransformHint(transformHint);
9602  
9603          WindowLayout.computeSurfaceSize(mWindowAttributes, winConfig.getMaxBounds(), requestedWidth,
9604                  requestedHeight, mWinFrameInScreen, mPendingDragResizing, mSurfaceSize);
9605  
9606          final boolean sizeChanged = !mLastSurfaceSize.equals(mSurfaceSize);
9607          final boolean surfaceControlChanged =
9608                  (relayoutResult & RELAYOUT_RES_SURFACE_CHANGED) == RELAYOUT_RES_SURFACE_CHANGED;
9609          if (mAttachInfo.mThreadedRenderer != null &&
9610                  (transformHintChanged || sizeChanged || surfaceControlChanged)) {
9611              if (mAttachInfo.mThreadedRenderer.pause()) {
9612                  // Animations were running so we need to push a frame
9613                  // to resume them
9614                  mDirty.set(0, 0, mWidth, mHeight);
9615              }
9616          }
9617  
9618          if (mSurfaceControl.isValid()) {
9619              if (mPendingDragResizing && !mSurfaceSize.equals(
9620                      mWinFrameInScreen.width(), mWinFrameInScreen.height())) {
9621                  // During drag-resize, a single fullscreen-sized surface is reused for optimization.
9622                  // Crop to the content size instead of the surface size to avoid exposing garbage
9623                  // content that is still on the surface from previous re-layouts (e.g. when
9624                  // resizing to a larger size).
9625                  mTransaction.setWindowCrop(mSurfaceControl,
9626                          mWinFrameInScreen.width(), mWinFrameInScreen.height());
9627              } else if (!HardwareRenderer.isDrawingEnabled()) {
9628                  // When drawing is disabled the window layer won't have a valid buffer.
9629                  // Set a window crop so input can get delivered to the window.
9630                  mTransaction.setWindowCrop(mSurfaceControl, mSurfaceSize.x, mSurfaceSize.y).apply();
9631              }
9632          }
9633  
9634          if (mAttachInfo.mContentCaptureManager != null) {
9635              ContentCaptureSession mainSession = mAttachInfo.mContentCaptureManager
9636                      .getMainContentCaptureSession();
9637              mainSession.notifyWindowBoundsChanged(mainSession.getId(),
9638                      getConfiguration().windowConfiguration.getBounds());
9639          }
9640  
9641          if (mSurfaceControl.isValid()) {
9642              updateBlastSurfaceIfNeeded();
9643              if (mAttachInfo.mThreadedRenderer != null) {
9644                  mAttachInfo.mThreadedRenderer.setSurfaceControl(mSurfaceControl, mBlastBufferQueue);
9645              }
9646              mHdrRenderState.forceUpdateHdrSdrRatio();
9647              if (transformHintChanged) {
9648                  dispatchTransformHintChanged(transformHint);
9649              }
9650          } else {
9651              if (mAttachInfo.mThreadedRenderer != null && mAttachInfo.mThreadedRenderer.pause()) {
9652                  mDirty.set(0, 0, mWidth, mHeight);
9653              }
9654              destroySurface();
9655          }
9656  
9657          if (restore) {
9658              params.restore();
9659          }
9660  
9661          setFrame(mTmpFrames.frame, true /* withinRelayout */);
9662          return relayoutResult;
9663      }

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

在Session的relayout的函数中,获取了WMS的service的对象,将上层传递的参数输入WMS的服务中

java 复制代码
public int relayout(IWindow window, WindowManager.LayoutParams attrs,
280              int requestedWidth, int requestedHeight, int viewFlags, int flags, int seq,
281              int lastSyncSeqId, WindowRelayoutResult outRelayoutResult) {
282          Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, mRelayoutTag);
283          int res = mService.relayoutWindow(this, window, attrs, requestedWidth,
284                  requestedHeight, viewFlags, flags, seq, lastSyncSeqId, outRelayoutResult);
285          Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
286          return res;
287      }
288  

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

WMS的函数中奖数据赋值给对应的属性,在这里我们只关注SurfaceControl的获取之路,该函数中会调用createSurfaceControl接口,创建一个包含父节点的SurfaceControl对象,赋值给outSurfaceControl

java 复制代码
    public int relayoutWindow(Session session, IWindow client, LayoutParams attrs,
2357              int requestedWidth, int requestedHeight, int viewVisibility, int flags, int seq,
2358              int lastSyncSeqId, WindowRelayoutResult outRelayoutResult) {
                  if (outRelayoutResult != null) {
2365              outFrames = outRelayoutResult.frames;
2366              outMergedConfiguration = outRelayoutResult.mergedConfiguration;
2367              outSurfaceControl = outRelayoutResult.surfaceControl;
2368              outInsetsState = outRelayoutResult.insetsState;
2369              outActiveControls = outRelayoutResult.activeControls;
2370          } else {
2371              outFrames = null;
2372              outMergedConfiguration = null;
2373              outSurfaceControl = null;
2374              outInsetsState = null;
2375              outActiveControls = null;
2376          }
2377  
        ·······
                 //从windwstate的参数中获取winAnimator
                  WindowStateAnimator winAnimator = win.mWinAnimator;
                  ·········
                  result = createSurfaceControl(outSurfaceControl, result, win, winAnimator);

}
               //从上面的接口传递的参数可以知道,outSurfaceControl这个就是java层的对象,接下来winAnimator通过createSurfaceLocked
               //开始获取父节点的SurfaceControl对象,通过getSurfaceControl函数,获取SF一个对应的Layer地址保存在mNativeObject,
               //后面BBQSurface会用到这个地址,将绘画的内容输入到layer
   private int createSurfaceControl(SurfaceControl outSurfaceControl, int result,
2845              WindowState win, WindowStateAnimator winAnimator) {
2846          if (!win.mHasSurface) {
2847              result |= RELAYOUT_RES_SURFACE_CHANGED;
2848          }
2849  
2850          SurfaceControl surfaceControl;
2851          try {
                  //通过winAnimator创建一个SurfaceControl对象
2853              surfaceControl = winAnimator.createSurfaceLocked();
2854          } finally {
2855              Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
2856          }
2857          if (surfaceControl != null) {
2858              winAnimator.getSurfaceControl(outSurfaceControl);
2859              ProtoLog.i(WM_SHOW_TRANSACTIONS, "OUT SURFACE %s: copied", outSurfaceControl);
2860  
2861          } else {
2862              // For some reason there isn't a surface.  Clear the
2863              // caller's object so they see the same state.
2864              ProtoLog.w(WM_ERROR, "Failed to create surface control for %s", win);
2865              outSurfaceControl.release();
2866          }
2867  
2868          return result;
2869      }
          ##WindowStateAnimator.java
SurfaceControl createSurfaceLocked() {
294          final WindowState w = mWin;
295  
296          if (mSurfaceControl != null) {
297              return mSurfaceControl;
298          }
299  
300          w.setHasSurface(false);
301  
302          ProtoLog.i(WM_DEBUG_ANIM, "createSurface %s: mDrawState=DRAW_PENDING", this);
303  
304          resetDrawState();
305  
306          int flags = SurfaceControl.HIDDEN;
307          final WindowManager.LayoutParams attrs = w.mAttrs;
308  
309          if ((mWin.mAttrs.privateFlags & PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY) != 0) {
310              flags |= SurfaceControl.SKIP_SCREENSHOT;
311          }
312  
313          if (DEBUG_VISIBILITY) {
314              Slog.v(TAG, "Creating surface " + this
315                      + " format=" + attrs.format + " flags=" + flags);
316          }
317  
318          // Set up surface control with initial size.
319          try {
320  
321              // This can be removed once we move all Buffer Layers to use BLAST.
322              final boolean isHwAccelerated = (attrs.flags & FLAG_HARDWARE_ACCELERATED) != 0;
323              final int format = isHwAccelerated ? PixelFormat.TRANSLUCENT : attrs.format;
324  
325              mTitle = attrs.getTitle().toString();
326              Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "new SurfaceControl");
327              mSurfaceControl = mWin.makeSurface()
328                      .setParent(mWin.mSurfaceControl)
329                      .setName(mTitle)
330                      .setFormat(format)
331                      .setFlags(flags)
332                      .setMetadata(METADATA_WINDOW_TYPE, attrs.type)
333                      .setMetadata(METADATA_OWNER_UID, mSession.mUid)
334                      .setMetadata(METADATA_OWNER_PID, mSession.mPid)
335                      .setCallsite("WindowSurfaceController")
336                      .setBLASTLayer().build();//setBLASTLayer  设置成BLASRLayer图层
337              Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
338  
339              if (!setScPropertiesInClient()) {
340                  setColorSpaceAgnosticLocked(
341                          (attrs.privateFlags & LayoutParams.PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC) != 0);
342              }
343  
344              w.setHasSurface(true);
345              // The surface instance is changed. Make sure the input info can be applied to the
346              // new surface, e.g. relaunch activity.
347              w.mInputWindowHandle.forceChange();
348  
349              ProtoLog.i(WM_SHOW_SURFACE_ALLOC,
350                      "  CREATE SURFACE %s: pid=%d format=%d flags=0x%x / %s",
351                      mSurfaceControl, mSession.mPid, attrs.format, flags, this);
352          } catch (OutOfResourcesException e) {
353              Slog.w(TAG, "OutOfResourcesException creating surface");
354              mService.mRoot.reclaimSomeSurfaceMemory(this, "create", true);
355              mDrawState = NO_SURFACE;
356              return null;
357          } catch (Exception e) {
358              Slog.e(TAG, "Exception creating surface (parent dead?)", e);
359              mDrawState = NO_SURFACE;
360              return null;
361          }
362  
363          if (DEBUG) {
364              Slog.v(TAG, "Got surface: " + mSurfaceControl
365                      + ", set left=" + w.getFrame().left + " top=" + w.getFrame().top);
366          }
367  
368          if (SHOW_LIGHT_TRANSACTIONS) {
369              Slog.i(TAG, ">>> OPEN TRANSACTION createSurfaceLocked");
370              WindowManagerService.logSurface(w, "CREATE pos=("
371                      + w.getFrame().left + "," + w.getFrame().top + ") HIDE", false);
372          }
373  
374          mLastHidden = true;
375  
376          if (DEBUG) Slog.v(TAG, "Created surface " + this);
377          return mSurfaceControl;
378      }

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

java 复制代码
    void getSurfaceControl(SurfaceControl outSurfaceControl) {
385          outSurfaceControl.copyFrom(mSurfaceControl, "WindowStateAnimator.getSurfaceControl");
386      }

 public void copyFrom(@NonNull SurfaceControl other, String callsite) {
1022          mName = other.mName;
1023          mWidth = other.mWidth;
1024          mHeight = other.mHeight;
1025          mLocalOwnerView = other.mLocalOwnerView;
1026          assignNativeObject(nativeCopyFromSurfaceControl(other.mNativeObject), callsite);
1027      }

1028  private void assignNativeObject(long nativeObject, String callsite) {
996          if (mNativeObject != 0) {
997              release();
998          }
999          if (nativeObject != 0) {
1000              mFreeNativeResources =
1001                      sRegistry.registerNativeAllocation(this, nativeObject);
1002          }
1003          mNativeObject = nativeObject;
              //这里会创建一个指向SF层的Layer的对象指针
1004          mNativeHandle = mNativeObject != 0 ? nativeGetHandle(nativeObject) : 0;
1005          if (sDebugUsageAfterRelease && mNativeObject == 0) {
1006              mReleaseStack = new Throwable("Assigned invalid nativeObject");
1007          } else {
1008              mReleaseStack = null;
1009          }
1010          setUnreleasedWarningCallSite(callsite);
1011          if (nativeObject != 0) {
1012              // Only add valid surface controls to the registry. This is called at the end of this
1013              // method since its information is dumped if the process threshold is reached.
1014              SurfaceControlRegistry.getProcessInstance().add(this);
1015          }
1016      }

frameworks/base/services/core/java/com/android/server/wm/WindowContainer.java **mWin 是WindowContainer对象**

在createSurfaceLocked方法中看到通过makeSurface创建的SurfaceControl。先获取父节点的窗口,传递当前的Task。是子容器调用的 makeChildSurface 方法,那子容器类就是 Task,父容器就是 DefaultTaskDisplayArea

执行 父容器 makeChildSurface方法的时候,又调用了getParent 获取父容器,执行 makeChildSurface,(眉头一皱,事情并不简单)这是开始递归了。

先不管递归,总之肯定的是 makeChildSurface方法不管怎么递归返回的还是一个SurfaceControl.Builder,然后调用setParent将DefaultTaskDisplayArea的Surface设置为其父节点。

这样一来,结果就是 :Task调用 父容器的makeChildSurface后,创建出了一个Surface,并且挂载到了父容器(DefaultTaskDisplayArea)的下面。知道结果后,还是要弄清楚 递归方法是怎么创建 Task对应的Surface的

对于递归调用,最终要的就是找到递归结束的条件,当前这个递归结束的条件就是 DisplayContent 类重写了makeChildSurface方法,也就是说调到 DisplayContent::makeChildSurface 就意味着递归的结束。

所以现在来看看 DisplayContent::makeChildSurface方法

java 复制代码
 # WindowContainer
       // 当前容器的Surface
       protected SurfaceControl mSurfaceControl;

       SurfaceControl.Builder makeSurface() {
          // 拿到父节点,调用makeChildSurface
          final WindowContainer p = getParent();
          // 传递当前,也就是Task
          return p.makeChildSurface(this);
       }

       SurfaceControl.Builder makeChildSurface(WindowContainer child) {
          // 拿到父亲
          final WindowContainer p = getParent();
          // Give the parent a chance to set properties. In hierarchy v1 we rely
          // on this to set full-screen dimensions on all our Surface-less Layers.
          // 调用父亲的makeChildSurface方法,再调用setParent 
          return p.makeChildSurface(child)
                    .setParent(mSurfaceControl);
       }
       //这里的参数 child 就是Task,
       //首先创建一个容器类型 SurfaceControl.Builder
       //设置name,当前场景是把Task的名字设置过去
      //然后设置一下父亲为DisplayContent的Surface
      //这里设置父节点最终是无效的,会被覆盖掉,因为上面分析看到了把 DefaultTaskDisplayArea设置为Task父容器。从代码的执行顺序上来说,
      //DisplayContent的这次setParent先执行,会被后面的覆盖掉。 从结果来看,Task也确实是挂在DefaultTaskDisplayArea下的
    # DisplayContent
       @Override
       SurfaceControl.Builder makeChildSurface(WindowContainer child) {
          SurfaceSession s = child != null ? child.getSession() : getSession();
          // 创建一个容器类型 SurfaceControl的Builder
          final SurfaceControl.Builder b = mWmService.makeSurfaceBuilder(s).setContainerLayer();
          if (child == null) {
             return b;
          }
          // 设置容器名
           return b.setName(child.getName())
                   .setParent(mSurfaceControl);
        }

winAnimator.getSurfaceControl接下来看下这个函数,创建SurfaceControl之后,通过这个方法给java层的SurfaceControl赋值,顺便在SF层指向了一个layer地址.

java 复制代码
 #WindowStateAnimator.java
void getSurfaceControl(SurfaceControl outSurfaceControl) { //
385          outSurfaceControl.copyFrom(mSurfaceControl, "WindowStateAnimator.getSurfaceControl");
386      }
#SurfaceControl.java
 public void copyFrom(@NonNull SurfaceControl other, String callsite) {
1022          mName = other.mName;
1023          mWidth = other.mWidth;
1024          mHeight = other.mHeight;
1025          mLocalOwnerView = other.mLocalOwnerView;
1026          assignNativeObject(nativeCopyFromSurfaceControl(other.mNativeObject), callsite);
1027      }
#SurfaceControl.java
private void assignNativeObject(long nativeObject, String callsite) {
996          if (mNativeObject != 0) {
997              release();
998          }
999          if (nativeObject != 0) {
1000              mFreeNativeResources =
1001                      sRegistry.registerNativeAllocation(this, nativeObject);
1002          }
1003          mNativeObject = nativeObject; //***这个对象就是Native的SurfaceControl且拥有SF的图层在createSurfaceLocked方法
                      //时build()创建的***
1004          mNativeHandle = mNativeObject != 0 ? nativeGetHandle(nativeObject) : 0;
1005          if (sDebugUsageAfterRelease && mNativeObject == 0) {
1006              mReleaseStack = new Throwable("Assigned invalid nativeObject");
1007          } else {
1008              mReleaseStack = null;
1009          }
1010          setUnreleasedWarningCallSite(callsite);
1011          if (nativeObject != 0) {
1012              // Only add valid surface controls to the registry. This is called at the end of this
1013              // method since its information is dumped if the process threshold is reached.
1014              SurfaceControlRegistry.getProcessInstance().add(this);
1015          }
1016      }
    //nativeCopyFromSurfaceControl 这个方法会调用native层的函数nativeCopyFromSurfaceControl,创建一个native层的SurfaceControl
    //并且开始赋值给Native的SurfaceControl
frameworks/base/core/jni/android_view_SurfaceControl.cpp
 static jlong nativeCopyFromSurfaceControl(JNIEnv* env, jclass clazz, jlong surfaceControlNativeObj) {
1994      sp<SurfaceControl> surface(reinterpret_cast<SurfaceControl *>(surfaceControlNativeObj));
1995      if (surface == nullptr) {
1996          return 0;
1997      }
1999      sp<SurfaceControl> newSurface = new SurfaceControl(surface);
2000      newSurface->incStrong((void *)nativeCreate);
2001      return reinterpret_cast<jlong>(newSurface.get());

持有SF的图层的部分,在末尾的时候进行补充,至此java层的SurfaceControl和native层的SurfaceControl的握手至此结束

Surface基于android 15源码分析

surface的创建也是开始relayoutWindow函数,当SurfaceControl创建之后,updateBlastSurfaceIfNeeded调用这个函数进行创建Surface,其实就是到native层创建一个surface,然后将SurfaceControl的mNativeObject指针附到native的surface里,然后传上来,在赋给jave层surface

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

java 复制代码
private int relayoutWindow(WindowManager.LayoutParams params, int viewVisibility,
9495              boolean insetsPending) throws RemoteException {
··············
if (relayoutAsync) {
9559              mWindowSession.relayoutAsync(mWindow, params,
9560                      requestedWidth, requestedHeight, viewVisibility,
9561                      insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0, mRelayoutSeq,
9562                      mLastSyncSeqId);
9563          } else {//眼熟吧,就是联通java层的SurfaceControl和native层的SurfaceControl的地方
9564              relayoutResult = mWindowSession.relayout(mWindow, params,
9565                      requestedWidth, requestedHeight, viewVisibility,
9566                      insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0,
9567                      mRelayoutSeq, mLastSyncSeqId, mRelayoutResult);
                   }
····················
        // mSurfaceControl这里已经是有效的啦啦啦~
 if (mSurfaceControl.isValid()) {
9642              updateBlastSurfaceIfNeeded();// 开启偷天换日了,直接通过移花接木的方式,将Surface的下面直接指向了BBQSurface了
9643              if (mAttachInfo.mThreadedRenderer != null) {
9644                  mAttachInfo.mThreadedRenderer.setSurfaceControl(mSurfaceControl, mBlastBufferQueue);
9645              }
9646              mHdrRenderState.forceUpdateHdrSdrRatio();
9647              if (transformHintChanged) {
9648                  dispatchTransformHintChanged(transformHint);
9649              }
9650          } else {
9651              if (mAttachInfo.mThreadedRenderer != null && mAttachInfo.mThreadedRenderer.pause()) {
9652                  mDirty.set(0, 0, mWidth, mHeight);
9653              }
9654              destroySurface();
9655          }
9656  
9657          if (restore) {
9658              params.restore();
9659          }
9660  
9661          setFrame(mTmpFrames.frame, true /* withinRelayout */);
9662          return relayoutResult;
}
### ViewRootImpl.java
    //createSurface这个先创建一个blastSurface
void updateBlastSurfaceIfNeeded() {
2807          if (!mSurfaceControl.isValid()) {
2808              return;
2809          }
2810  
2811          if (mBlastBufferQueue != null && mBlastBufferQueue.isSameSurfaceControl(mSurfaceControl)) {
2812              mBlastBufferQueue.update(mSurfaceControl,
2813                  mSurfaceSize.x, mSurfaceSize.y,
2814                  mWindowAttributes.format);
2815              return;
2816          }
2817  
2818          // If the SurfaceControl has been updated, destroy and recreate the BBQ to reset the BQ and
2819          // BBQ states.
2820          if (mBlastBufferQueue != null) {
2821              mBlastBufferQueue.destroy();
2822          }
2823          mBlastBufferQueue = new BLASTBufferQueue(mTag, true /* updateDestinationFrame */);
2824          // If we create and destroy BBQ without recreating the SurfaceControl, we can end up
2825          // queuing buffers on multiple apply tokens causing out of order buffer submissions. We
2826          // fix this by setting the same apply token on all BBQs created by this VRI.
2827          mBlastBufferQueue.setApplyToken(mBbqApplyToken);
              //在这里已经开始,将mSurfaceControl的mhandle(指向SF的Layer的指针)给了BlastBufferQueue了
2828          mBlastBufferQueue.update(mSurfaceControl,  mSurfaceSize.x, mSurfaceSize.y,
2829                  mWindowAttributes.format);
2830          mBlastBufferQueue.setTransactionHangCallback(sTransactionHangCallback);
2831          mBlastBufferQueue.setWaitForBufferReleaseCallback(mChoreographer::onWaitForBufferRelease);
2832          Surface blastSurface;
2833          if (addSchandleToVriSurface()) {
2834              blastSurface = mBlastBufferQueue.createSurfaceWithHandle();
2835          } else {
2836              blastSurface = mBlastBufferQueue.createSurface(); //创建好了blastSurface了
2837          }
2838          // Only call transferFrom if the surface has changed to prevent inc the generation ID and
2839          // causing EGL resources to be recreated.
2840          mSurface.transferFrom(blastSurface);  //偷天换日的接口
2841  
2842          // Since the SurfaceControl is a VRI, indicate that it can recover from buffer stuffing.
2843          mTransaction.setRecoverableFromBufferStuffing(mSurfaceControl).applyAsyncUnsafe();
2844      }
// frameworks/base/core/java/android/view/Surface.java
 public void transferFrom(Surface other) {
789          if (other == null) {
790              throw new IllegalArgumentException("other must not be null");
791          }
792          if (other != this) {
793              final long newPtr;
794              synchronized (other.mLock) {
795                  newPtr = other.mNativeObject;  //图层的偷偷换掉
796                  other.setNativeObjectLocked(0); // 将other的地址偷偷的释放了
797              }
798  
799              synchronized (mLock) {
800                  if (mNativeObject != 0) {
801                      nativeRelease(mNativeObject);
802                  }
803                  setNativeObjectLocked(newPtr); //偷偷的绑定新的对象
804              }
805          }
806      }
807  

frameworks/base/graphics/java/android/graphics/BLASTBufferQueue.java

通过jni的方式调用底层的代码nativeGetSurface方法,这里关键的方法在getSurface中,可以看到在getSurface方法中,获取了BLASTBufferQueue的scHandle对象(在 mBlastBufferQueue.update(mSurfaceControl,...)这这里将java层SurfaceControl的指向native的SurfaceControl的指针),BBQSurface拿到这个scHandle就开始创建了。

java 复制代码
     public Surface createSurface() {
85          return nativeGetSurface(mNativeObject, false /* includeSurfaceControlHandle */);
86      }
//frameworks/base/core/jni/android_graphics_BLASTBufferQueue.cpp
 static jobject nativeGetSurface(JNIEnv* env, jclass clazz, jlong ptr,
139                                  jboolean includeSurfaceControlHandle) {
140      sp<BLASTBufferQueue> queue = reinterpret_cast<BLASTBufferQueue*>(ptr);
141      return android_view_Surface_createFromSurface(env,
142                                                    queue->getSurface(includeSurfaceControlHandle));
143  }

frameworks/native/libs/gui/BLASTBufferQueue.cpp
 sp<Surface> BLASTBufferQueue::getSurface(bool includeSurfaceControlHandle) {
1020      std::lock_guard _lock{mMutex};
1021      sp<IBinder> scHandle = nullptr;
1022      if (includeSurfaceControlHandle && mSurfaceControl) {
1023          scHandle = mSurfaceControl->getHandle();
1024      }
1025      return sp<BBQSurface>::make(mProducer, true, scHandle, this);
1026  }
//BBQSurface是BLASTBufferQueue的内部类
public:  //在构造方法中可以看到,将scHandle赋值给了Surface的scHandle,持有指定的SF的图层的地方了
935      BBQSurface(const sp<IGraphicBufferProducer>& igbp, bool controlledByApp,
936                 const sp<IBinder>& scHandle, const sp<BLASTBufferQueue>& bbq)
937            : Surface(igbp, controlledByApp, scHandle), mBbq(bbq) {}

frameworks/base/core/jni/android_view_Surface.cpp
//创建了一个对象返回上层了

 static struct {
62      jclass clazz;
63      jfieldID mNativeObject;//native的SurfaceControl,连着SF的layer
64      jfieldID mLock;
65      jmethodID ctor;
66  } gSurfaceClassInfo;

jobject android_view_Surface_createFromSurface(JNIEnv* env, const sp<Surface>& surface) {
122      jobject surfaceObj = env->NewObject(gSurfaceClassInfo.clazz,
123              gSurfaceClassInfo.ctor, (jlong)surface.get());
124      if (surfaceObj == NULL) {
125          if (env->ExceptionCheck()) {
126              ALOGE("Could not create instance of Surface from IGraphicBufferProducer.");
127              LOGE_EX(env);
128              env->ExceptionClear();
129          }
130          return NULL;
131      }
132      surface->incStrong(&sRefBaseOwner);
133      return surfaceObj;
134  }
到这里SurfaceControl和Surface的关系就扯清楚了,接下来就是Vsync信号配合layer的合成下发了,越来越精彩,哈哈哈
相关推荐
weixin_444012932 小时前
c++如何将std--vector直接DUMP到二进制文件_指针地址直写【附代码】
jvm·数据库·python
woxihuan1234562 小时前
Go语言中--=运算符详解:位右移赋值操作的原理与应用
jvm·数据库·python
石山代码2 小时前
Python 数据分析三大库:NumPy + Pandas + Matplotlib
python·数据分析·numpy
如竟没有火炬2 小时前
用队列实现栈
开发语言·数据结构·python·算法·leetcode·深度优先
折哥的程序人生 · 物流技术专研2 小时前
《Java 100 天进阶之路》第17篇:Java常用包装类与自动装箱拆箱深入
java·开发语言·后端·面试
yivifu2 小时前
CustomTkinter的布局管理器介绍及应用
python·gui·customtkinter·pdf去水印
m0_690825823 小时前
如何备份被破坏的数据表_强制跳过错误的导出尝试
jvm·数据库·python
C+++Python3 小时前
C 语言 动态内存分配:malloc /calloc/realloc /free
c语言·开发语言
tongyiixiaohuang3 小时前
轻易云平台助力快麦数据入库MySQL
android·数据库·mysql