首页 > 其他分享 >Android SurfaceFlinger——创建Surface(二十一)

Android SurfaceFlinger——创建Surface(二十一)

时间:2024-07-02 14:55:32浏览次数:18  
标签:const struct int ANativeWindow Surface SurfaceFlinger Android NATIVE

        通过前面的篇文章我们简单了解了 Surface 和 Layer,并且知道了 SurfaceComposerClient 的 createSurface() 方法最终创建的其实是一个 Layer,这里我们来看一下真正的获取 Surface 的方法。

一、获取Surface

        通过系统动画的播放流程中我们知道真正获取 Surface 的方法是 SurfaceControl 中的 getSurface() 函数,这里我们先来看一下 SurfaceControl 的构造函数。

1、SurfaceControl

源码位置:/frameworks/native/libs/gui/SurfaceControl.cpp

SurfaceControl::SurfaceControl(const sp<SurfaceComposerClient>& client, const sp<IBinder>& handle,
            const sp<IGraphicBufferProducer>& gbp, int32_t layerId, uint32_t w, uint32_t h, 
            PixelFormat format, uint32_t transform, uint32_t flags)
    : mClient(client),
    mHandle(handle),
    mGraphicBufferProducer(gbp),
    mLayerId(layerId),
    mTransformHint(transform),
    mWidth(w),
    mHeight(h),
    mFormat(format),
    mCreateFlags(flags) {}

        此时 SurfaceControl 同时持有了 Client 的 Binder,图元生产者以及 SurfaceComposerClient 服务。 当 SurfaceControl 有了之后,需要绘制像素,是绘制在 SurfaceControl 生成的 Surface 上。

getSurface

sp<Surface> SurfaceControl::getSurface()
{
    Mutex::Autolock _l(mLock);
    if (mSurfaceData == nullptr) {
        return generateSurfaceLocked();
    }
    return mSurfaceData;
}

        这里调用了 generateSurfaceLocked() 函数。

generateSurfaceLocked 

sp<Surface> SurfaceControl::generateSurfaceLocked()
{
    uint32_t ignore;
    auto flags = mCreateFlags & (ISurfaceComposerClient::eCursorWindow | ISurfaceComposerClient::eOpaque);
    // 这里创建一个新的名为"bbq-wrapper"的Layer
    mBbqChild = mClient->createSurface(String8("bbq-wrapper"), 0, 0, mFormat, flags, mHandle, {}, &ignore);
    // 创建BLASTBufferQueue
    mBbq = sp<BLASTBufferQueue>::make("bbq-adapter", mBbqChild, mWidth, mHeight, mFormat);

    // 从BLASTBufferQueue中获取实际的Surface对象
    mSurfaceData = mBbq->getSurface(true);

    return mSurfaceData;
}

        该函数为 SurfaceControl 实例创建并返回一个 Surface 对象。这个 Surface 对象是通过创建一个中间的 BufferQueue(BBQ,即 BLASTBufferQueue)图层来间接获得的,用于图形内容的显示和管理。 

2、BLASTBufferQueue.cpp

源码位置:/frameworks/native/libs/gui/BLASTBufferQueue.cpp

sp<Surface> BLASTBufferQueue::getSurface(bool includeSurfaceControlHandle) {
    std::unique_lock _lock{mMutex};
    sp<IBinder> scHandle = nullptr;
    if (includeSurfaceControlHandle && mSurfaceControl) {
        scHandle = mSurfaceControl->getHandle();
    }
    return new BBQSurface(mProducer, true, scHandle, this);
}

class BBQSurface : public Surface {
}

        这里创建一个 BBQSurface,而 BBQSurface 又继承自 Surface,所以这里就完成了 Surface 的创建。也就是把图元生产者设置到 Surface 中。

二、Surface初始化

        Surface 才是面向我们客户端,开发者的绘制图层。我们不会直接操作图元生产者。一切的事情都交给 Surface 来发送。这里面包含了很重要的图元发送等逻辑。

1、Surface.h

源码位置:/frameworks/native/libs/gui/include/gui/Surface.h

/**
 * ANativeWindow的实现,它将图形缓冲区提供给BufferQueue
 */
class Surface : public ANativeObjectBase<ANativeWindow, Surface, RefBase>

        可以看到 Surface 继承了一个 ANativeObjectBase 模版类,这个模版类只是处理引用计数。

2、ANativeObjectBase.h 

源码位置:/frameworks/native/libs/ui/include/ui/ANativeObjectBase.h

/*
 * 这个助手类将ANativeXXX对象类型转换为c++引用计数对象;使用适当的类型转换。
 */
template <typename NATIVE_TYPE, typename TYPE, typename REF,
        typename NATIVE_BASE = android_native_base_t>
class ANativeObjectBase : public NATIVE_TYPE, public REF
{
public:
    // 消除REF中的incStrong和NATIVE_TYPE之间的歧义
    void incStrong(const void* id) const {
        REF::incStrong(id);
    }
    void decStrong(const void* id) const {
        REF::decStrong(id);
    }

protected:
    typedef ANativeObjectBase<NATIVE_TYPE, TYPE, REF, NATIVE_BASE> BASE;
    ANativeObjectBase() : NATIVE_TYPE(), REF() {
        NATIVE_TYPE::common.incRef = incRef;
        NATIVE_TYPE::common.decRef = decRef;
    }
    static inline TYPE* getSelf(NATIVE_TYPE* self) {
        return static_cast<TYPE*>(self);
    }
    static inline TYPE const* getSelf(NATIVE_TYPE const* self) {
        return static_cast<TYPE const *>(self);
    }
    static inline TYPE* getSelf(NATIVE_BASE* base) {
        return getSelf(reinterpret_cast<NATIVE_TYPE*>(base));
    }
    static inline TYPE const * getSelf(NATIVE_BASE const* base) {
        return getSelf(reinterpret_cast<NATIVE_TYPE const*>(base));
    }
    static void incRef(NATIVE_BASE* base) {
        ANativeObjectBase* self = getSelf(base);
        self->incStrong(self);
    }
    static void decRef(NATIVE_BASE* base) {
        ANativeObjectBase* self = getSelf(base);
        self->decStrong(self);
    }
};

         使用模版了类决定了继承关系。换句话说其实相当于一个 Hook,在不改变设计结构下,增加了引用的特性。

3、ANativeWindow

源码位置:/frameworks/native/libs/nativewindow/include/system/window.h

struct ANativeWindow
{
#ifdef __cplusplus
    ANativeWindow()
        : flags(0), minSwapInterval(0), maxSwapInterval(0), xdpi(0), ydpi(0)
    {
        common.magic = ANDROID_NATIVE_WINDOW_MAGIC;
        common.version = sizeof(ANativeWindow);
        memset(common.reserved, 0, sizeof(common.reserved));
    }

    /* 实现sp<ANativeWindow>期望的方法,以便它可以用来自动重新计算ANativeWindow的。 */
    void incStrong(const void* /*id*/) const {
        common.incRef(const_cast<android_native_base_t*>(&common));
    }
    void decStrong(const void* /*id*/) const {
        common.decRef(const_cast<android_native_base_t*>(&common));
    }
#endif

    struct android_native_base_t common;

    /* 描述此表面或其更新程序的某些属性的标志 */
    const uint32_t flags;

    /* 此更新支持的最小交换缓冲 */
    const int minSwapInterval;

    /* 此更新支持的最大交换缓冲 */
    const int maxSwapInterval;

    /* DPI中的水平和垂直分辨率 */
    const float xdpi;
    const float ydpi;

    /* 一些存储保留给OEM的驱动程序 */
    intptr_t oem[4];

    /* 设置该表面的交换缓冲 */
    int (*setSwapInterval)(struct ANativeWindow* window, int interval);

    /* 由EGL调用以获取缓冲区的Hook */
    int (*dequeueBuffer_DEPRECATED)(struct ANativeWindow* window, struct ANativeWindowBuffer** buffer);

    /* 由EGL调用来锁定缓冲区的Hook */
    int (*lockBuffer_DEPRECATED)(struct ANativeWindow* window, struct ANativeWindowBuffer* buffer);

    /* 由EGL调用完成对渲染缓冲区的修改的Hook */
    int(*queueBuffer_DEPRECATED)(struct ANativeWindow* window, struct ANativeWindowBuffer* buffer);

    /* 用于检索有关本机窗口的信息Hook */
    int (*query)(const struct ANativeWindow* window, int what, int* value);

    /* 用于在表面执行各种操作Hook */
    int (*perform)(struct ANativeWindow* window, int operation, ... );

    /* 用于取消已退出队列的缓冲区Hook */
    int (*cancelBuffer_DEPRECATED)(struct ANativeWindow* window, struct ANativeWindowBuffer* buffer);

    /* 由EGL调用以获取缓冲区的Hook */
    int (*dequeueBuffer)(struct ANativeWindow* window, struct ANativeWindowBuffer** buffer, int* fenceFd);

    /* 由EGL调用完成对渲染缓冲区的修改的Hook */
    int (*queueBuffer)(struct ANativeWindow* window, struct ANativeWindowBuffer* buffer, int fenceFd);

    /* 用于取消已退出队列的缓冲区的Hook */
    int (*cancelBuffer)(struct ANativeWindow* window, struct ANativeWindowBuffer* buffer, int fenceFd);
};

        这里别看名叫 Window,实际上 ANativeWindow 不是作为图元存储的结构体,他是用来控制 ANativeWindowBuffer 像素缓存的。大致上有四个操作,queueBuffer 图元入队,dequeueBuffer 图元出队,lockBuffer 图元锁定,query 图元查找等。当然还有setSwapInterval 交换缓冲。

        接下来再来看看整个 Surface 的初始化。

4、Surface

源码位置:/frameworks/native/libs/gui/Surface.cpp

Surface::Surface(const sp<IGraphicBufferProducer>& bufferProducer, bool controlledByApp,
                 const sp<IBinder>& surfaceControlHandle)
      : mGraphicBufferProducer(bufferProducer),
        mCrop(Rect::EMPTY_RECT),
        mBufferAge(0),
        mGenerationNumber(0),
        mSharedBufferMode(false),
        mAutoRefresh(false),
        mAutoPrerotation(false),
        mSharedBufferSlot(BufferItem::INVALID_BUFFER_SLOT),
        mSharedBufferHasBeenQueued(false),
        mQueriedSupportedTimestamps(false),
        mFrameTimestampsSupportsPresent(false),
        mEnableFrameTimestamps(false),
        mFrameEventHistory(std::make_unique<ProducerFrameEventHistory>()) {
    // Initialize the ANativeWindow function pointers.
    ANativeWindow::setSwapInterval  = hook_setSwapInterval;
    ANativeWindow::dequeueBuffer    = hook_dequeueBuffer;
    ANativeWindow::cancelBuffer     = hook_cancelBuffer;
    ANativeWindow::queueBuffer      = hook_queueBuffer;
    ANativeWindow::query            = hook_query;
    ANativeWindow::perform          = hook_perform;

    ANativeWindow::dequeueBuffer_DEPRECATED = hook_dequeueBuffer_DEPRECATED;
    ANativeWindow::cancelBuffer_DEPRECATED  = hook_cancelBuffer_DEPRECATED;
    ANativeWindow::lockBuffer_DEPRECATED    = hook_lockBuffer_DEPRECATED;
    ANativeWindow::queueBuffer_DEPRECATED   = hook_queueBuffer_DEPRECATED;

    const_cast<int&>(ANativeWindow::minSwapInterval) = 0;
    const_cast<int&>(ANativeWindow::maxSwapInterval) = 1;

    mReqWidth = 0;
    mReqHeight = 0;
    mReqFormat = 0;
    mReqUsage = 0;
    mTimestamp = NATIVE_WINDOW_TIMESTAMP_AUTO;
    mDataSpace = Dataspace::UNKNOWN;
    mScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE;
    mTransform = 0;
    mStickyTransform = 0;
    mDefaultWidth = 0;
    mDefaultHeight = 0;
    mUserWidth = 0;
    mUserHeight = 0;
    mTransformHint = 0;
    mConsumerRunningBehind = false;
    mConnectedToCpu = false;
    mProducerControlledByApp = controlledByApp;
    mSwapIntervalZero = false;
    mMaxBufferCount = NUM_BUFFER_SLOTS;
    mSurfaceControlHandle = surfaceControlHandle;
}

        在 Surface 初始化的时候,同时为每一个方法指针都赋值了,让 Surface 拥有了操作的能力。

总结

        其实整个过程就是图元缓冲队列的初始化流程。在这个初始化流程中,初步的搭建了整个生产者-消费者模型。剩下的步骤就是生产图元,写入生产者,生产者把数据写进缓冲队列,通知消费者进行消费。

  • createSurface 通过 SurfaceFlinger 的 Client 对象创建了一个图元生产者,并且赋值给 SurfaceControl 中。
  • setLayer 设置 layer  图层在 Z 轴上的层级。
  • getSurface 通过 SurfaceControl 生产 Surface 对象,真正进行交互是 Surface 对象。

标签:const,struct,int,ANativeWindow,Surface,SurfaceFlinger,Android,NATIVE
From: https://blog.csdn.net/c19344881x/article/details/140046960

相关文章

  • Android super.img结构及解包和重新组包
    Androidsuper.img结构及解包和重新组包从Android10版本开始,Android系统使用动态分区,system、vendor、odm等都包含在super.img里面,编译后的最终镜像不再有这些单独的image,取而代之的是一个总的super.img.1.基础知识1.1为什么用super分区代替独立的分区?传统的分区方......
  • 关于AndroidStudio中的onCreate方法
    onCreate方法是Android应用程序中的一个生命周期方法,它是每个Activity(活动)都必须实现的方法之一。具体来说,它是在Activity第一次创建时调用的方法,用于完成一些初始化设置和布局加载工作。主要作用设置布局:通过调用setContentView方法来加载指定的布局文件,将界面内......
  • RK3568 android13 预置APK
    现象:需要预置一个测试APK,按照以往得方法,将APK放到device/rockchip/rk356x/rk3568_t/preinstall目录下面。然后编译成新得固件。发现桌面没有显示APK。 查看OUT目录下面有预置得APK,out/target/product/rk3568_t/odm/bundled_persist-app/autotest/autotest.apk。说明APK是有......
  • Android 监听网络状态变化(无切换中间态版)
    需求:获取当前的网络状态与类型(WIFI、数据流量)监听网络状态真正变化监听网络类型发生变化业务场景:用户打开App时、使用过程中,出现无网络时,显示Toast提示。但当wifi、数据流量互相切换的过程中不要有提示。下载功能支持检测到用户连接上wifi时开启静默下载,当换成数据......
  • Android应用启动流程一次看透
    1.1、冷启动和热启动冷启动:当启动应用时,后台没有该应用的进程,这时系统会重新创建一个新的进程分配给该应用,然后再根据启动的参数,启动对应的进程组件,这个启动方式就是冷启动。热启动:当启动应用时,后台已有该应用的进程(例:按back键、home键,应用虽然会退出,但是该应用的进程是依然......
  • Android系统之System Server大纲
    前言SystemServer是android基本服务的提供者,是android系统运行的最基本需求,所有server运行在一个叫system_process的进程中,system_process进程是androidjava虚拟机跑的第一个进程,从Zygote创建而来,是andorid系统最重要的java虚拟机。可以说,整个android系统的业务都是围绕syste......
  • Android Gradle 开发与应用 (三): 依赖管理与版本控制
    目录1.依赖管理的重要性1.1依赖的类型1.2Gradle中的依赖声明2.版本控制的策略2.1固定版本与动态版本2.2版本冲突的解决3.Gradle插件的使用3.1常用的Gradle插件3.2自定义插件4.多模块项目中的依赖管理4.1模块间依赖4.2公共依赖5.依赖版本管理的最......
  • 【转】Androidstudio报错Algorithm HmacPBESHA256 not available
     删除debug.keystone这个文件就可以了。 https://blog.csdn.net/O_PUTI/article/details/138227534 -----参考了更改GradleJDK等的办法都没有用,最终通过一个一个问题拍错解决。第一个问题:版本不一致 第二个问题秘钥获取不成功:删除这个文件 然后就编译成功了。......
  • 【RK3588】Android系统OTA升级详细流程(三)
    接着上一篇文章,做一下OTA包远程升级测试。1.搭建OTA升级服务器Ubuntu系统下搭建OTA服务器。我们将使用Tomcat来搭建web服务器,Tomcat是一个免费、开源的轻量级web应用服务器。1.1安装JDKTomcat依赖于Java运行环境,所以需要先安装Java环境。可自行前往JavaArchive|Oracle......
  • 适用于 Android 的 几种短信恢复应用程序
    Android设备上的短信丢失可能由于多种原因而丢失,例如意外删除、恢复出厂设置、系统崩溃或病毒攻击。是否有应用程序可以恢复Android上已删除的短信?幸运的是,有几款短信恢复应用程序可以扫描您的Android手机并从内存或SIM卡中检索已删除的短信。然而,并非所有短信恢复应用......