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。

Android之Surface

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

 

    

 

上一篇:CDH 6.2 安装 Phoenix


下一篇:Error spawn parcel ENOENT