Android Surface 是如何跨进程传递的?
创始人
2024-01-29 04:35:55
0

Android Surface 跨进程传递原理?

  • Surface
  • Activity 的 Surface 是怎么跨进程传递的
  • 问题

Surface

public class Surface implements Parcelable {// ....long mNativeObject;private final Canvas mCanvas = new CompatibleCanvas();// ....
}
	首先,Surface 实现了 Parcelable,所以它是可以跨进程传递的。Parcelable 关键的函数就是 readFromParcel(Parcel source) 和 writeToParcel(Parcel dest, int flags) 
  • writeToParcel()
    @Overridepublic void writeToParcel(Parcel dest, int flags) {// ...synchronized (mLock) {// 写了个 mNamedest.writeString(mName);dest.writeInt(mIsSingleBuffered ? 1 : 0);// 调用了 native 方法 nativeWriteToParcel 写入了一个 mNativeObject 对象nativeWriteToParcel(mNativeObject, dest);}}

writeToParcel 方法写入了一个 mName 变量,然后调用 nativeWriteToParcel 函数写入了 mNativeObject 对象。long mNativeObject; 是一个 native对象的指针。

	private static native void nativeWriteToParcel(long nativeObject, Parcel dest);
  • readFromParcel 函数
    public void readFromParcel(Parcel source) {synchronized (mLock) {mName = source.readString();mIsSingleBuffered = source.readInt() != 0;setNativeObjectLocked(nativeReadFromParcel(mNativeObject, source));}}
	private static native long nativeReadFromParcel(long nativeObject, Parcel source);

readFromParcel 和 writeToParcel 相比,他是反过来读取一个 mName 值,然后通过 mNativeObject 传入nativeReadFromParcel 中,在调用 setNativeObjectLocked() 函数。设置了一些属性。

  • setNativeObjectLocked()
    private void setNativeObjectLocked(long ptr) {if (mNativeObject != ptr) {// 。。。mNativeObject = ptr;}}

setNativeObjectLocked 函数把传入的 long 类型的地址赋值给了 mNativeObject 。

  • 目前java层来看的话就是操作了一个 long 类型的mNativeObject 变量和一个 mName 属性。接下来看一下 native 层的实现

      frameworks/base/core/jni/android_view_Surface.cpp
    
  • 先看一下 nativeWriteToParcel() 函数

static void nativeWriteToParcel(JNIEnv* env, jclass clazz,jlong nativeObject, jobject parcelObj) {// 通过 parcelForJavaObject 函数获得了一个 native 层的 Parcel 对象Parcel* parcel = parcelForJavaObject(env, parcelObj);// nativeObject 就是 surface 在 native 层的指针// 所以通过该指针获得 surface 的对象sp self(reinterpret_cast(nativeObject));android::view::Surface surfaceShim;if (self != nullptr) {// 获取一个 GraphicBuffersurfaceShim.graphicBufferProducer = self->getIGraphicBufferProducer();}// 将 GraphicBuffer 对象写到 parcelsurfaceShim.writeToParcel(parcel, /*nameAlreadyWritten*/true);
}
  • parcelForJavaObject()
Parcel* parcelForJavaObject(JNIEnv* env, jobject obj)
{if (obj) {// 通过 jni ,从Java层的 Parcel 对象获得了一个 native 层的 Parcel 对象。Parcel* p = (Parcel*)env->GetLongField(obj, gParcelOffsets.mNativePtr);if (p != NULL) {return p;}}return NULL;
}

上面方法通过 jni ,从Java层的 Parcel 对象获得了一个 native 层的 Parcel 对象。因为Java层对象中保存了一个 native 层对象的指针。

  • nativeReadFromParcel
static jlong nativeReadFromParcel(JNIEnv* env, jclass clazz,jlong nativeObject, jobject parcelObj) {// 先 parcel 对象拿到 native 的 Parcel 对象Parcel* parcel = parcelForJavaObject(env, parcelObj);// 定义 surfaceShim 指定是 android view surfaceandroid::view::Surface surfaceShim;surfaceShim.readFromParcel(parcel, /*nameAlreadyRead*/true);sp self(reinterpret_cast(nativeObject));// 只有当底层的IGraphicBufferProducer发生变化时才更新Surface。if (self != nullptr&& (IInterface::asBinder(self->getIGraphicBufferProducer()) ==IInterface::asBinder(surfaceShim.graphicBufferProducer))) {// same IGraphicBufferProducer, return ourselvesreturn jlong(self.get());}sp sur;if (surfaceShim.graphicBufferProducer != nullptr) {// 创建一个 surface 对象,传入 IGraphicBufferProducersur = new Surface(surfaceShim.graphicBufferProducer, true);// and keep a reference before passing to javasur->incStrong(&sRefBaseOwner);}if (self != NULL) {// and loose the java reference to ourselvesself->decStrong(&sRefBaseOwner);}// 返回新创建的 surface 对象给 Java 层return jlong(sur.get());
}
  • Java层的surface 在于 native 层的 surface,而 native 层的 surface 在于 graphicBufferProducer 对象,它是可以申请 buffer 的存在。

Activity 的 Surface 是怎么跨进程传递的

performTraversals() 是准备绘制的时候,当第一次绘制的时候代码如下

private void performTraversals() {if(mFirst){int relayoutResult = 0;relayoutResult = relayoutWindow(params, viewVisibility, insetsPending);}
}
  • 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,mWinFrame, mPendingOverscanInsets, mPendingContentInsets, mPendingVisibleInsets,mPendingStableInsets, mPendingOutsets, mPendingBackDropFrame, mPendingDisplayCutout,mPendingMergedConfiguration, mSurface);return relayoutResult;}

mWindowSession binder 对象会给 wms 申请 relayout 调用,这里面会申请surface。传入的 mSurface 只是一个空壳。
relayout() 是一个 aidl 接口源码中是这样描述它的,总之就是调用这个方法,可以返回一个 surface 对象,你可以用它展示内容。mWindowSession 实际上就是 Java 层和 wms 交流的桥梁

     * Change the parameters of a window.  You supply the* new parameters, it returns the new frame of the window on screen (the* position should be ignored) and surface of the window.  The surface* will be invalid if the window is currently hidden, else you can use it* to draw the window's contents.

调用该这个 aidl 方法执行 framework 中 Session.java
在这里插入图片描述

    @Overridepublic 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,Surface outSurface) {int res = mService.relayoutWindow(this, window, seq, attrs,requestedWidth, requestedHeight, viewFlags, flags, frameNumber,outFrame, outOverscanInsets, outContentInsets, outVisibleInsets,outStableInsets, outsets, outBackdropFrame, cutout,mergedConfiguration, outSurface);return res;}
  • mService.relayoutWindow()

public int relayoutWindow(Session session, IWindow client, int seq, LayoutParams attr...{// 调用了 createSurfaceControl() 方法中有下面代码WindowSurfaceController surfaceController;surfaceController = winAnimator.createSurfaceLocked(win.mAttrs.type, win.mOwnerUid);// getSurface 里面调用了 outSurface.copyFrom(mSurfaceControl);surfaceController.getSurface(outSurface);
}
  • surface 从 surfaceController 中 copy 了一些东西
    public void copyFrom(SurfaceControl other) {// SurfaceControl 也保存了 native 层的对象long surfaceControlPtr = other.mNativeObject;// 根据 native 层的SurfaceControl对象创建一个native层的 surface 对象long newNativeObject = nativeGetFromSurfaceControl(surfaceControlPtr);synchronized (mLock) {if (mNativeObject != 0) {nativeRelease(mNativeObject);}// 然后将 native层的 surface 对象 和 java层的 surface 对象绑定到一起setNativeObjectLocked(newNativeObject);}}

上面方法创建了 native 层的 surface 对象 并且和Java层的surface 层对象绑定一起,在创建对象的时候,
long newNativeObject = nativeGetFromSurfaceControl(surfaceControlPtr); 创建了一个 Surface对象,并且传入了 mGraphicBufferProducer 。也就是 SurfaceControl 中有一个 mGraphicBufferProducer 然后根据 mGraphicBufferProducer 创建了一个native 层 Surface 对象,然后将 native 层的 Surface 对象的指针,保存到 Java 层 Surface 对象中。

问题

  1. 怎么理解 surface 它是一块 buffer 么?

     	所以 surface 实际上有作用的是 GraphicBufferProducer 对象,它可以生成 buffer 。
    
  2. 如果是 buffer ,surface 如何跨进程携带它的?

     所以它不是 buffer 它携带的是 GraphicBufferProducer ,GraphicBufferProducer 是一个 binder 对象。
    

相关内容

热门资讯

喜欢穿一身黑的男生性格(喜欢穿... 今天百科达人给各位分享喜欢穿一身黑的男生性格的知识,其中也会对喜欢穿一身黑衣服的男人人好相处吗进行解...
发春是什么意思(思春和发春是什... 本篇文章极速百科给大家谈谈发春是什么意思,以及思春和发春是什么意思对应的知识点,希望对各位有所帮助,...
网络用语zl是什么意思(zl是... 今天给各位分享网络用语zl是什么意思的知识,其中也会对zl是啥意思是什么网络用语进行解释,如果能碰巧...
为什么酷狗音乐自己唱的歌不能下... 本篇文章极速百科小编给大家谈谈为什么酷狗音乐自己唱的歌不能下载到本地?,以及为什么酷狗下载的歌曲不是...
华为下载未安装的文件去哪找(华... 今天百科达人给各位分享华为下载未安装的文件去哪找的知识,其中也会对华为下载未安装的文件去哪找到进行解...
怎么往应用助手里添加应用(应用... 今天百科达人给各位分享怎么往应用助手里添加应用的知识,其中也会对应用助手怎么添加微信进行解释,如果能...
家里可以做假山养金鱼吗(假山能... 今天百科达人给各位分享家里可以做假山养金鱼吗的知识,其中也会对假山能放鱼缸里吗进行解释,如果能碰巧解...
四分五裂是什么生肖什么动物(四... 本篇文章极速百科小编给大家谈谈四分五裂是什么生肖什么动物,以及四分五裂打一生肖是什么对应的知识点,希...
一帆风顺二龙腾飞三阳开泰祝福语... 本篇文章极速百科给大家谈谈一帆风顺二龙腾飞三阳开泰祝福语,以及一帆风顺二龙腾飞三阳开泰祝福语结婚对应...
美团联名卡审核成功待激活(美团... 今天百科达人给各位分享美团联名卡审核成功待激活的知识,其中也会对美团联名卡审核未通过进行解释,如果能...