zoukankan      html  css  js  c++  java
  • Android之Surface

    一、Surface是什么

      Handle onto a raw buffer that is being managed by the screen compositor.

      大概意思是处理由屏幕合成器管理的原理缓存区。

    二、Surface实现原理

      在Surface类里有一个Canvas对象,在Canvas里有一个Bitmap,Bitmap是真正的画布。

      Bitmap是什么

      Bitmap缩写是BMP,是一种存储像素的数据结构。

    三、Surface跨进程间传递

      源码:frameworks/base/core/java/android/view/Surface.java

    /**
     * Handle onto a raw buffer that is being managed by the screen compositor.
     *
     * <p>A Surface is generally created by or from a consumer of image buffers (such as a
     * {@link android.graphics.SurfaceTexture}, {@link android.media.MediaRecorder}, or
     * {@link android.renderscript.Allocation}), and is handed to some kind of producer (such as
     * {@link android.opengl.EGL14#eglCreateWindowSurface(android.opengl.EGLDisplay,android.opengl.EGLConfig,java.lang.Object,int[],int) OpenGL},
     * {@link android.media.MediaPlayer#setSurface MediaPlayer}, or
     * {@link android.hardware.camera2.CameraDevice#createCaptureSession CameraDevice}) to draw
     * into.</p>
     *
     * <p><strong>Note:</strong> A Surface acts like a
     * {@link java.lang.ref.WeakReference weak reference} to the consumer it is associated with. By
     * itself it will not keep its parent consumer from being reclaimed.</p>
     */
    public class Surface implements Parcelable {
        ……
    }
    

      Surface继承自Parcelable,Parcelable是一个序列化接口,将对象转化为二进制流(二进制序列)的过程。二进制流可以通过Socket传输或者保存到本地。

      在Android中Surface是怎么在进程间传递的,应用如何将Surface传递给SurfaceFlinger进程绘制的。

      Java层实现:

      在Parcelable中有两个关键函数:

    /**
     * 将数据写入Parcel对象
     */
    public void writeToParcel(Parcel dest, int flags) {}
    /**
     * 从Parcel对象中读取数据
     */
    public void readFromParcel(Parcel source) {}

      先看Parcelable.writeToParcel()函数:

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        synchronized (mLock) {
            // NOTE: This must be kept synchronized with the native parceling code
            // in frameworks/native/libs/Surface.cpp
            dest.writeString(mName);
            dest.writeInt(mIsSingleBuffered ? 1 : 0);
            nativeWriteToParcel(mNativeObject, dest);
        }
    }

      dest是一个Parcel对象,将name写入Parcel对象dest,再调用nativeWriteToParcel()函数,将mNativeObject写入到Parcel对象。

      mNativeObject是什么?

    long mNativeObject; // package scope only for SurfaceControl access

      mNativeObject是Long型变量,存储Native层的对象指针。

      nativeWriteToParcel()函数定义:

    private static native void nativeWriteToParcel(long nativeObject, Parcel dest);

      nativeWriteToParcel()函数是Native层函数。

      下面看看readFromParcel()函数:

    public void readFromParcel(Parcel source) {
        synchronized (mLock) {
            // nativeReadFromParcel() will either return mNativeObject, or
            // create a new native Surface and return it after reducing
            // the reference count on mNativeObject.  Either way, it is
            // not necessary to call nativeRelease() here.
            // NOTE: This must be kept synchronized with the native parceling code
            // in frameworks/native/libs/Surface.cpp
            mName = source.readString();
            mIsSingleBuffered = source.readInt() != 0;
            setNativeObjectLocked(nativeReadFromParcel(mNativeObject, source));
        }
    }

      从Surface对象中读取name数据,再调用nativeReadFromParcel()函数,通过setNativeObjectLocked()函数将nativeReadFromParcel()函数返回的数据保存起来。

      nativeReadFromParcel()函数定义:

    private static native long nativeReadFromParcel(long nativeObject, Parcel source);

      setNativeObjectLocked()函数实现:

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

      将nativeReadFromParcel()函数返回值赋值给mNativeObject变量。

      Native层:

      源码:frameworks/base/core/jni/android_view_Surface.cpp

      nativeWriteToParcel()函数实现:

    static void nativeWriteToParcel(JNIEnv* env, jclass clazz,
            jlong nativeObject, jobject parcelObj) {
        // (1) 获取parcel对象,从Java层
        Parcel* parcel = parcelForJavaObject(env, parcelObj);
        if (parcel == NULL) {
            jniThrowNullPointerException(env, NULL);
            return;
        }
        // (2) Native层的Surface对象
        sp<Surface> self(reinterpret_cast<Surface *>(nativeObject));
        android::view::Surface surfaceShim;
        if (self != nullptr) {
            // (3)
            surfaceShim.graphicBufferProducer = self->getIGraphicBufferProducer();
        }
        // Calling code in Surface.java has already written the name of the Surface
        // to the Parcel
        surfaceShim.writeToParcel(parcel, /*nameAlreadyWritten*/true);
    }
    
    // (3) 
    sp<IGraphicBufferProducer> GraphicBufferSource::getIGraphicBufferProducer() const {
        return mProducer;
    }    

      (1) 通过parcelFroJavaOjbect()获取Parcel对象:

    Parcel* parcelForJavaObject(JNIEnv* env, jobject obj)
    {
        if (obj) {
            Parcel* p = (Parcel*)env->GetLongField(obj, gParcelOffsets.mNativePtr);
            if (p != NULL) {
                return p;
            }
            jniThrowException(env, "java/lang/IllegalStateException", "Parcel has been finalized!");
        }
        return NULL;
    }

      (1) 通过JNI调用,在Native层通过Native层保存的Java层Parcel指针获取Native层对应Java层的Parcel对象。

      (2) 通过Native层保存的Java层Surface对象指针,在Native层恢复Surface对象。

      (3) 将Native层的IGraphicBufferProducer对象传递给Java层的Surface.graphicBufferProducer变量。

      nativeReadFromParcel()函数实现:

    static jlong nativeReadFromParcel(JNIEnv* env, jclass clazz,
            jlong nativeObject, jobject parcelObj) {
        // (1)
        Parcel* parcel = parcelForJavaObject(env, parcelObj);
    
        android::view::Surface surfaceShim;
        // (2)
        sp<Surface> self(reinterpret_cast<Surface *>(nativeObject));
    
        // update the Surface only if the underlying IGraphicBufferProducer
        // has changed.
        // (3)
        if (self != nullptr
                && (IInterface::asBinder(self->getIGraphicBufferProducer()) ==
                        IInterface::asBinder(surfaceShim.graphicBufferProducer))) {
            // same IGraphicBufferProducer, return ourselves
            return jlong(self.get());
        }
    
        // (4)
        sp<Surface> sur;
        if (surfaceShim.graphicBufferProducer != nullptr) {
            // we have a new IGraphicBufferProducer, create a new Surface for it
            sur = new Surface(surfaceShim.graphicBufferProducer, true);
            // and keep a reference before passing to java
            sur->incStrong(&sRefBaseOwner);
        }
    
        if (self != NULL) {
            // and loose the java reference to ourselves
            self->decStrong(&sRefBaseOwner);
        }
    
        // (5)
        return jlong(sur.get());
    }

      (1) 获取Native层对应Java层的Parcel对象。 

      (2) 获取Native层对应Java层的Surface对象。

      (3) 获取IGraphicBufferProducer对象,一个Binder对象。

      (4) 通过IGraphicBufferProducer对象创建一个新的Surface对象。

      (5) 将Native层的新Surface对象通过JNI调用传递给Java层。

      对象Java层的Surface对应Native层的Surface对象,对于Native层的Surface对应Native层的IGraphicBufferProducer对象。

    四、总结

      Android App中,一个Window对应一个Surface对象,应用与绘制服务SurfaceFlinger服务的通信是基于共享内存实现的,应用中在Java层将Surface对象通过Parcel转化为二进制流,并且二进制流存储在共享内存。

      Android每个应用都有在共享内存中都会有一个SharedClicent,再应用的Window对应一个Surface,而每个Surface对应共享内存的SharedBufferStack。

      Surface中Buffer是没有进程跨进程传递的,应用与SurfaceFlinger服务通信传递的是共享内存的物理地址,应用将Surface的Buffer写入到SharedClient中,再将SharedClient中的SharedBufferStack的地址通过Binder通信传递给SurfaceFlinger。SurfaceFlinger服务通过共享内存的物理地址到SharedClicent读取SharedBufferStack数据。

      在SharedBufferStack中分为双缓冲与三级缓冲,在Android 4.1版本前是双缓冲机制,在4.1版本后是三级缓冲机制。

      SharedBufferStack分为:

      • FontBuffer:在屏幕中显示。
      • BackBuffer:绘制Buffer。
      • Triple Buffer:是Android对绘制优化,Vsync垂直同步提供的机制。Triple Buffer是CPU/GPU在空闲时提前准备数据的Buffer。

       PS:可以配合SurfaceFlinger一文一起阅读。

        

  • 相关阅读:
    java学习第六天
    java学习第五天
    java学习第四天
    java学习第三天
    java学习第二天
    java学习第一天
    性能测试学习第十三天_性能测试报告编写
    性能测试学习第十二天_性能分析
    性能测试学习第十一天_Analysis
    性能测试学习第十天_controller
  • 原文地址:https://www.cnblogs.com/naray/p/15340006.html
Copyright © 2011-2022 走看看