Android图形显示系统——下层显示3:窗口系统

简介: Android之窗口系统要点1.Android窗口系统通过C-S架构和一套Buffer循环机制实现,在保证安全稳定的前提下基本上做到了极致性能(无大块内存拷贝,IPC通信内容最少)。 2.SurfaceFlinger创建Layer,将其中的BufferQueueProducer作为IGraphicBufferProducer传给应用侧的Surface,因而构成窗

Android之窗口系统

要点

1.Android窗口系统通过C-S架构和一套Buffer循环机制实现,在保证安全稳定的前提下基本上做到了极致性能(无大块内存拷贝,IPC通信内容最少)。
2.SurfaceFlinger创建Layer,将其中的BufferQueueProducer作为IGraphicBufferProducer传给应用侧的Surface,因而构成窗口。
3.Surface是皮,BufferQueue是肉,通过这样的皮肉关系构建了Buffer循环机制。Buffer循环机制不仅用于窗口系统,也用于视频播放解码流,相机拍照数据流等(Camera2.0架构)。

注:代码基于Android 5.0

窗口系统接口

作为一个应用,绘图是自由的,基本上也是平台无关的。但如果要把绘图的结果显示出来,就必须依赖平台提供的窗口系统。好比我们写篇文章出来容易,要投到杂志上发表,就必须按杂志社的格式,并通过审校等一堆流程,不然每个人都随便发,肯定乱套了。

Android的窗口系统设计

窗口类型
Android为应用层提供的窗口接口为ANativeWindow。这个接口可用来调整配置参数,获取图形内存并送还触发显示。应用层是Buffer的生产者。
对于非GPU绘图的应用,通过这个类去获取图形内存(dequeueBuffer),并在绘制完成之后送还(queueBuffer),让显示系统在合适的时机显示。
对于GPU绘图(严格来说,是使用EGL标准)的应用,在创建OpenGL上下文时将ANativeWindow的指针传入,GPU的驱动会在合适的时候完成获取内存和送还的操作。应用层只需要调用eglSwapBuffers换缓存即可。

Android的Windows接口

对应用层开放的windows接口定义在
system/core/include/system/windows.h
主要接口函数如下:

struct ANativeWindow
{
    /*......*/
    int     (*setSwapInterval)(struct ANativeWindow* window, int interval);//设置Buffer失效期限,当应用生产Buffer快于消费者(一般是显示系统)的消费时,这个参数决定是否丢弃之前没来得及消费的Buffer。
    int     (*query)(const struct ANativeWindow* window, int what, int* value);//查询参数
    int     (*perform)(struct ANativeWindow* window,int operation, ... );//设置参数,其中也包括做连接
    int     (*dequeueBuffer)(struct ANativeWindow* window, struct ANativeWindowBuffer** buffer, int* fenceFd);//从队列中取出一块Buffer用于生产(一般是图形渲染),若是第一次调用,会触发Buffer的申请
    int     (*queueBuffer)(struct ANativeWindow* window, struct ANativeWindowBuffer* buffer, int fenceFd);//将生产完成的Buffer送还
    int     (*cancelBuffer)(struct ANativeWindow* window,  struct ANativeWindowBuffer* buffer, int fenceFd);//释放Buffer队列中的Buffer,一般是disconnect时调用
};
AI 代码解读

用于perform和query接口的一些宏定义如下:

/*用于perform和query接口的宏*/
enum {
    NATIVE_WINDOW_SET_USAGE                 =  0,
    NATIVE_WINDOW_CONNECT                   =  1,   /* deprecated */
    NATIVE_WINDOW_DISCONNECT                =  2,   /* deprecated */
    NATIVE_WINDOW_SET_CROP                  =  3,   /* private */
    NATIVE_WINDOW_SET_BUFFER_COUNT          =  4,
    NATIVE_WINDOW_SET_BUFFERS_GEOMETRY      =  5,   /* deprecated */
    NATIVE_WINDOW_SET_BUFFERS_TRANSFORM     =  6,
    NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP     =  7,
    NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS    =  8,
    NATIVE_WINDOW_SET_BUFFERS_FORMAT        =  9,
    NATIVE_WINDOW_SET_SCALING_MODE          = 10,   /* private */
    NATIVE_WINDOW_LOCK                      = 11,   /* private */
    NATIVE_WINDOW_UNLOCK_AND_POST           = 12,   /* private */
    NATIVE_WINDOW_API_CONNECT               = 13,   /* private */
    NATIVE_WINDOW_API_DISCONNECT            = 14,   /* private */
    NATIVE_WINDOW_SET_BUFFERS_USER_DIMENSIONS = 15, /* private */
    NATIVE_WINDOW_SET_POST_TRANSFORM_CROP   = 16,   /* private */
    NATIVE_WINDOW_SET_BUFFERS_STICKY_TRANSFORM = 17,/* private */
    NATIVE_WINDOW_SET_SIDEBAND_STREAM       = 18,
    NATIVE_WINDOW_SET_BUFFERS_DATASPACE     = 19
};
AI 代码解读

窗口的创建与使用

Surface

自Android 4.2之后,FramebufferNativeWindow被废弃,所有窗口均继承Surface。Surface本身是一种ANativeWindow。

class Surface
    : public ANativeObjectBase<ANativeWindow, Surface, RefBase>/*Surface继承于ANativeWindow*/
{
public:
    Surface(const sp<IGraphicBufferProducer>& bufferProducer, bool controlledByApp = false);
    /*......*/
private:
    // ANativeWindow hooks
    /*这几个hook函数对应于 window.h 中的接口函数*/
    static int hook_cancelBuffer(ANativeWindow* window,
            ANativeWindowBuffer* buffer, int fenceFd);
    static int hook_dequeueBuffer(ANativeWindow* window,
            ANativeWindowBuffer** buffer, int* fenceFd);
    static int hook_perform(ANativeWindow* window, int operation, ...);
    static int hook_query(const ANativeWindow* window, int what, int* value);
    static int hook_queueBuffer(ANativeWindow* window,
            ANativeWindowBuffer* buffer, int fenceFd);
    static int hook_setSwapInterval(ANativeWindow* window, int interval);

    static int hook_cancelBuffer_DEPRECATED(ANativeWindow* window,
            ANativeWindowBuffer* buffer);
    static int hook_dequeueBuffer_DEPRECATED(ANativeWindow* window,
            ANativeWindowBuffer** buffer);
    static int hook_lockBuffer_DEPRECATED(ANativeWindow* window,
            ANativeWindowBuffer* buffer);
    static int hook_queueBuffer_DEPRECATED(ANativeWindow* window,
            ANativeWindowBuffer* buffer);
    /*.......*/
public:
    /*这两个函数主要是CPU绘图时调用,除了获取,映射Buffer之外,额外将非脏区域从上一块Buffer拷贝到本块Buffer,以便渲染时只绘制脏区域*/
    virtual int lock(ANativeWindow_Buffer* outBuffer, ARect* inOutDirtyBounds);
    virtual int unlockAndPost();
    /*.......*/
private:
    struct BufferSlot {
        sp<GraphicBuffer> buffer;
        Region dirtyRegion;
    };
    /*Buffer生产者,Surface*/
    sp<IGraphicBufferProducer> mGraphicBufferProducer;
    BufferSlot mSlots[NUM_BUFFER_SLOTS];
    /*通过native_window_set_buffers_dimensions改变,用于在合适的时机改变GraphicBuffer的长宽*/
    uint32_t mReqWidth;
    uint32_t mReqHeight;
    /*需求的GraphicBuffer格式,用于动态调整*/
    PixelFormat mReqFormat;
    /*需求Usage说明,影响GraphicBuffer的flags*/
    uint32_t mReqUsage;
    /*时间戳,用于判断Buffer是否过期*/
    int64_t mTimestamp;
    /*Buffer的使用范围*/
    Rect mCrop;
    /*Buffer后续变换需求,只包括水平、垂直翻转,90度旋转*/
    uint32_t mTransformHint;
    /*BufferProducer是否由使用Surface的App控制,这个主要是用来决定dequeueBuffer时是否堵塞*/
    bool mProducerControlledByApp;
    /*......*/
};

}; // namespace android
AI 代码解读

窗口的创建

用于图形显示的窗口,是由SurfaceFlinger进程负责创建的:
Surface创建
为应用层创建Surface(窗口)时,SurfaceFlinger同步创建一个Layer,并将Layer的生产者关联到Surface上。这样,应用侧便可以通过Surface申请Buffer,作为生产者渲染图像,送显由Layer中的消费者负责。

Buffer循环机制

对于按一定帧率刷新的窗口系统,每一次渲染只有很有限的时间,频繁地申请/释放图形内存是不可接受的。Android的做法是维护一个Buffer队列,按生产者——消费者模式循环利用。这个Buffer就是上一章所述的GraphicBuffer。

Buffer的状态

Buffer队列池中持有固定数量的Buffer(由setBufferCount函数决定,一般是3块),每个Buffer有四种状态,决定其是否可以被生产者/消费者访问。
Buffer状态变化

Buffer的生产

序号化

由于Layer位于SurfaceFlinger进程中,GraphicBuffer是在SurfaceFlinger进程中创建的。应用层作为生产者,使用时需要将其映射到自己的进程空间。在每次申请Buffer时都做一次映射很不明智。
很容易想到的一个方法是在应用层建一个GraphicBuffer队列,和SurfaceFlinger中的Buffer队列对应地映射起来,每次申请和返还时,以序号代替真实的GraphicBuffer传替。Android也正是这么做的。

dequeueBuffer

Surface::dequeueBuffer(android_native_buffer_t** buffer, int* fenceFd)
这接口用于申请内存进行生产(渲染)。
于Surface侧,它获取Buffer的序列号,然后检查是否已经同步过,若没有同步过调用requestBuffer同步(映射共享内存)。
于BufferQueue侧,它检查是否有 FREE 标志的Buffer,如果没有,根据 mProducerControlledByApp 标志决定返回错误码或者等待。
fenceFd是BufferQueue返回给Surface的,生产者有义务去等fence。

queueBuffer

int Surface::queueBuffer(android_native_buffer_t* buffer, int fenceFd)
于Surface侧,它将Buffer送还给BufferQueue,但这不一定表示生产者用完了,消费者获取到Buffer之后仍有义务等fence。
于BufferQueue侧,接收到Buffer,将其放到一个可用队列中,修改状态,并且触发监听器的onFrameAvailable函数。

Buffer的消费

acquireBuffer

消费者获取buffer,由于在queueBuffer时,会将Buffer放到一个队列中,这时便从那个队列去取。

releaseBuffer

消费者释放buffer。

相关文章
Android系统版本演进与未来展望####
本文深入探讨了Android操作系统从诞生至今的发展历程,详细阐述了其关键版本迭代带来的创新特性、用户体验提升及对全球移动生态系统的影响。通过对Android历史版本的回顾与分析,本文旨在揭示其成功背后的驱动力,并展望未来Android可能的发展趋势与面临的挑战,为读者呈现一个既全面又具深度的技术视角。 ####
移动应用与系统:探索Android开发之旅
在这篇文章中,我们将深入探讨Android开发的各个方面,从基础知识到高级技术。我们将通过代码示例和案例分析,帮助读者更好地理解和掌握Android开发。无论你是初学者还是有经验的开发者,这篇文章都将为你提供有价值的信息和技巧。让我们一起开启Android开发的旅程吧!
深入探索Android系统的内存管理机制
本文旨在全面解析Android系统的内存管理机制,包括其工作原理、常见问题及其解决方案。通过对Android内存模型的深入分析,本文将帮助开发者更好地理解内存分配、回收以及优化策略,从而提高应用性能和用户体验。
探索Android系统的最新安全特性
在数字时代,智能手机已成为我们生活中不可或缺的一部分。随着技术的不断进步,手机操作系统的安全性也越来越受到重视。本文将深入探讨Android系统最新的安全特性,包括其设计理念、实施方式以及对用户的影响。通过分析这些安全措施如何保护用户免受恶意软件和网络攻击的威胁,我们希望为读者提供对Android安全性的全面了解。
深入探讨Android系统的内存管理机制
本文将深入分析Android系统的内存管理机制,包括其内存分配、回收策略以及常见的内存泄漏问题。通过对这些方面的详细讨论,读者可以更好地理解Android系统如何高效地管理内存资源,从而提高应用程序的性能和稳定性。
131 16
深入探讨Android与iOS系统的差异及未来发展趋势
本文旨在深入分析Android和iOS两大移动操作系统的核心技术差异、用户体验以及各自的市场表现,进一步探讨它们在未来技术革新中可能的发展方向。通过对比两者的开放性、安全性、生态系统等方面,本文揭示了两大系统在移动设备市场中的竞争态势和潜在变革。
【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
41 8
【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
167 20
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
49 4
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex

热门文章

最新文章

  • 1
    【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
    16
  • 2
    Android历史版本与APK文件结构
    11
  • 3
    【01】噩梦终结flutter配安卓android鸿蒙harmonyOS 以及next调试环境配鸿蒙和ios真机调试环境-flutter项目安卓环境配置-gradle-agp-ndkVersion模拟器运行真机测试环境-本地环境搭建-如何快速搭建android本地运行环境-优雅草卓伊凡-很多人在这步就被难倒了
    28
  • 4
    当flutter react native 等混开框架-并且用vscode-idea等编译器无法打包apk,打包安卓不成功怎么办-直接用android studio如何打包安卓apk -重要-优雅草卓伊凡
    2
  • 5
    APP-国内主流安卓商店-应用市场-鸿蒙商店上架之必备前提·全国公安安全信息评估报告如何申请-需要安全评估报告的资料是哪些-优雅草卓伊凡全程操作
    11
  • 6
    【03】仿站技术之python技术,看完学会再也不用去购买收费工具了-修改整体页面做好安卓下载发给客户-并且开始提交网站公安备案-作为APP下载落地页文娱产品一定要备案-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
    3
  • 7
    【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
    3
  • 8
    【02】仿站技术之python技术,看完学会再也不用去购买收费工具了-本次找了小影-感觉页面很好看-本次是爬取vue需要用到Puppeteer库用node.js扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
    2
  • 9
    Cellebrite UFED 4PC 7.71 (Windows) - Android 和 iOS 移动设备取证软件
    4
  • 10
    【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
    1
  • AI助理

    你好,我是AI助理

    可以解答问题、推荐解决方案等