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一文一起閱讀。

 

    

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM