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

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 对象。
    

相关内容

热门资讯

埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
平遥古城在哪 平遥古城基本现状 城垣恢宏,雉堞连云市井街巷,店肆林立四合院落,青砖瓦屋这里是平遥古城历经千年沧桑而古朴宛然,风姿依旧...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
平遥古城在哪 平遥古城基本现状 城垣恢宏,雉堞连云市井街巷,店肆林立四合院落,青砖瓦屋这里是平遥古城历经千年沧桑而古朴宛然,风姿依旧...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...