Android图形缓冲区分配过程源码分析中介绍了图形buffer的分配过程,图形buffer可以从系统帧缓冲区分配也可以从内存中分配,分配一个图形buffer后还需要将该图形缓冲区映射到分配该buffer的进程地址空间来,在Android系统中,图形buffer的管理由SurfaceFlinger服务来负责,在Android
SurfaceFlinger服务启动过程源码分析中我们了解到SurfaceFlinger可以以服务进程的方式启动也可以以服务线程的方式在SystemServer进程中启动,如果是以服务进程的方式启动,那么创建的图形缓冲区就将映射到SurfaceFlinger进程地址空间;如果是以服务线程的方式在SystemServer中启动,那么创建的图形缓冲区将映射到SystemServer进程地址空间。在系统帧缓冲区中分配的图形缓冲区是在SurfaceFlinger服务中使用,而在内存中分配的图形缓冲区既可以在SurfaceFlinger服务中使用,也可以在其它的应用程序中使用。当其它的应用程序需要使用图形缓冲区的时候,它们就会请求SurfaceFlinger服务为它们分配并将SurfaceFlinger服务返回来的图形缓冲区映射到应用程序进程地址空间。图形缓冲区的分配过程在Android图形缓冲区分配过程源码分析中已经分析过了,在从内存中分配buffer时,已经将分配的buffer映射到了SurfaceFlinger服务进程地址空间,如果该buffer是应用程序请求SurfaceFlinger服务为它们分配的,那么还需要将SurfaceFlinger服务返回来的图形缓冲区映射到应用程序进程地址空间,本文介绍图形缓冲区映射到应用程序进程地址空间的过程。
Android提供了GraphicBufferMapper工具类,该类为上层访问Gralloc模块中的gralloc_module_t提供了接口,采用单例模式构造GraphicBufferMapper对象。
GraphicBufferMapper::GraphicBufferMapper(): mAllocMod(0)
{
hw_module_t const* module;
//根据模块ID得到模块描述符的首地址
int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
ALOGE_IF(err, "FATAL: can't find the %s module", GRALLOC_HARDWARE_MODULE_ID);
if (err == 0) {
//将hw_module_t的指针转换为gralloc_module_t类型指针
mAllocMod = (gralloc_module_t const *)module;
}
}
硬件抽象层模块的加载过程在
Android硬件抽象Hardware库加载过程源码分析中有详细的分析,这里根据模块ID加载Gralloc模块,并得到Gralloc模块的HMI符号首地址,并强制转换为gralloc_module_t类型指针。
GraphicBufferMapper提供了访问Gralloc模块的gralloc_module_t接口,GraphicBuffer就是通过其成员变量mBufferMapper来注册buffer的。
GraphicBuffer::unflatten()
-->GraphicBufferMapper::registerBuffer()
-->mAllocMod->registerBuffer()
-->gralloc_register_buffer()
GraphicBuffer::free_handle()
-->GraphicBufferMapper::unregisterBuffer()
-->mAllocMod->unregisterBuffer()
-->gralloc_unregister_buffer()
GraphicBuffer::lock()
-->GraphicBufferMapper::lock()
-->mAllocMod->lock()
-->gralloc_lock()
GraphicBuffer::unlock()
-->GraphicBufferMapper::unlock()
-->mAllocMod->unlock()
-->gralloc_unlock()
registerBuffer和unregisterBuffer分别用来注册和注销一个指定的图形缓冲区,所谓注册图形缓冲区,实际上就是将一块图形缓冲区映射到一个进程的地址空间去,而注销图形缓冲区就是执行相反的操作。lock和unlock分别用来锁定和解锁一个指定的图形缓冲区,在访问一块图形缓冲区的时候,例如,向一块图形缓冲写入内容的时候,需要将该图形缓冲区锁定,用来避免访问冲突。在锁定一块图形缓冲区的时候,可以指定要锁定的图形绘冲区的位置以及大小,这是通过参数l、t、w和h来指定的,其中,参数l和t指定的是要访问的图形缓冲区的左上角位置,而参数w和h指定的是要访问的图形缓冲区的宽度和长度。锁定之后,就可以获得由参数参数l、t、w和h所圈定的一块缓冲区的起始地址,保存在输出参数vaddr中。另一方面,在访问完成一块图形缓冲区之后,需要解除这块图形缓冲区的锁定。
1. 图形缓冲区的注册过程
status_t GraphicBufferMapper::registerBuffer(buffer_handle_t handle)
{
ATRACE_CALL();
status_t err;
err = mAllocMod->registerBuffer(mAllocMod, handle);
return err;
}
这里直接通过成员变量mAllocMod来调用gralloc_module_t中的registerBuffer函数来注册图形buffer
int gralloc_register_buffer(gralloc_module_t const* module,buffer_handle_t handle)
{
//校验图形buffer
if (private_handle_t::validate(handle) < 0)
return -EINVAL;
// if this handle was created in this process, then we keep it as is.
int err = 0;
private_handle_t* hnd = (private_handle_t*)handle;
//判断当前进程是否为创建该图形buffer的进程,如果是创建该图形buffer的进程,则不需要在重复映射了,因为在创建过程中已经完成了地址空间的映射过程
if (hnd->pid != getpid()) {
void *vaddr;
err = gralloc_map(module, handle, &vaddr);
}
return err;
}
这里的图形缓冲区的注册过程是针对应用程序进程的,服务端负责创建图形buffer,同时在创建的过程中自动将创建的图形buffer映射到服务进程地址空间,应用程序进程通过Binder进程间通信机制得到服务进程返回来的图形buffer,依然需要映射到应用程序进程,这样应用程序进程才能直接访问该图形buffer。这里通过进程ID号来区分当前进程是否为创建图形buffer的进程。
static int gralloc_map(gralloc_module_t const* module,
buffer_handle_t handle,
void** vaddr)
{
private_handle_t* hnd = (private_handle_t*)handle;
if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) {
size_t size = hnd->size;
void* mappedAddress = mmap(0, size,PROT_READ|PROT_WRITE, MAP_SHARED, hnd->fd, 0);
if (mappedAddress == MAP_FAILED) {
ALOGE("Could not mmap %s", strerror(errno));
return -errno;
}
hnd->base = intptr_t(mappedAddress) + hnd->offset;
}
*vaddr = (void*)hnd->base;
return 0;
}
这里通过系统调用mmap将服务端创建的图形缓冲区映射到应用程序进程地址空间。
2. 图形缓冲区的注销过程
图形缓冲区的注销过程和注册过程恰恰相反,函数调用过程类型,就是取消地址空间映射。
status_t GraphicBufferMapper::unregisterBuffer(buffer_handle_t handle)
{
ATRACE_CALL();
status_t err;
err = mAllocMod->unregisterBuffer(mAllocMod, handle);
ALOGW_IF(err, "unregisterBuffer(%p) failed %d (%s)",handle, err, strerror(-err));
return err;
}
直接调用gralloc_module_t中的unregisterBuffer函数来注销图形buffer
int gralloc_unregister_buffer(gralloc_module_t const* module,buffer_handle_t handle)
{
if (private_handle_t::validate(handle) < 0)
return -EINVAL;
// never unmap buffers that were created in this process
private_handle_t* hnd = (private_handle_t*)handle;
if (hnd->pid != getpid()) {
if (hnd->base) {
gralloc_unmap(module, handle);
}
}
return 0;
}
通过进程ID来判断是否需要取消映射
static int gralloc_unmap(gralloc_module_t const* module,buffer_handle_t handle)
{
private_handle_t* hnd = (private_handle_t*)handle;
if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) {
void* base = (void*)hnd->base;
size_t size = hnd->size;
if (munmap(base, size) < 0) {
ALOGE("Could not unmap %s", strerror(errno));
}
}
hnd->base = 0;
return 0;
}
调用munmap系统调用来取消图形buffer映射过程。
3. 图形缓冲区的锁定过程
status_t GraphicBufferMapper::lock(buffer_handle_t handle,
int usage, const Rect& bounds, void** vaddr)
{
ATRACE_CALL();
status_t err;
err = mAllocMod->lock(mAllocMod, handle, usage,
bounds.left, bounds.top, bounds.width(), bounds.height(),vaddr);
ALOGW_IF(err, "lock(...) failed %d (%s)", err, strerror(-err));
return err;
}
直接调用gralloc_module_t中的lock函数来锁定该图形buffer
int gralloc_lock(gralloc_module_t const* module,
buffer_handle_t handle, int usage,
int l, int t, int w, int h,
void** vaddr)
{
//根据硬件来具体实现
return 0;
}
4. 图形缓冲区的解锁过程
status_t GraphicBufferMapper::unlock(buffer_handle_t handle)
{
ATRACE_CALL();
status_t err;
err = mAllocMod->unlock(mAllocMod, handle);
ALOGW_IF(err, "unlock(...) failed %d (%s)", err, strerror(-err));
return err;
}
直接调用gralloc_module_t中的unlock函数来解锁该图形buffer
int gralloc_unlock(gralloc_module_t const* module, buffer_handle_t handle)
{
if (private_handle_t::validate(handle) < 0)
return -EINVAL;
//根据硬件来具体实现
...
return 0;
}
分享到:
相关推荐
一、实验目的 1. 理解缓冲区分析和叠置分析的基本原理。 2. 学习缓冲区分析、利用Arc Toolbox进行叠加分析的操作。 3. 掌握如何合理利用空间分析中的缓冲区分析和叠置分析解决实际问题。
环形缓冲区建立源码 环形缓冲区建立源码 环形缓冲区建立源码
《缓冲区溢出攻防》的源码,很多人找我要,所以共享一下。只是雕虫小技,自己玩玩就行了,不要用于其它用途。 http://blog.csdn.net/LocalVar/archive/2004/05/29/3615025.aspx
AEC#何如做缓冲区分析,本人实际经验总结
缓冲区溢出程序代码分析 缓冲溢出是指一种攻击系统的手段,通过往程序的缓冲区中写入超出其长度的内容造成溢出,从而破坏程序的堆栈,使程序转而执行其它指令,而达到攻击的目的。分布式拒绝服务(ddos)的入侵者...
这是一个关于缓冲区分析的C#实现代码,很好用!
war-ftp的一个版本中存在缓冲区溢出漏洞。这里利用C#编写了一个完整的利用工具(有源码),首先通过telnet登录到war-ftp服务器,然后向其发送超长字符串,程序崩溃。经过调试(实验报告中有详细的调试过程,压缩包里...
ArcGIs Server 缓冲区查询源码
Android 三种圆形缓冲的进度条源码.rar
Cesium 绘制缓冲区 点 线 面缓冲区 预览:http://dongnan185.com:8083/videos/draw.mp4 启动:npm i npm run serve
缓冲区分析是最常用的一种空间分析,在道路拓宽、流域季节性扩张、设施服务范围等分析中经常需要用到左右缓冲半径不等的缓冲区分析,本范例将示范如何进行左右缓冲半径不等的线对象和整个数据集的缓冲区分析。
在Windows XP VC++6.0环境下运行通过的缓冲区溢出程序源码
提出一种应用在3维数字地球中的通过图形处理器(GPU)快速实现矢量数据缓冲区分析的算法。使用一张4通道的纹理图作为容器将地理实体的矢量数据传人GPU,利用GPU的高效并行特性,将目标缓冲区纹理中的每个像素所对应的...
使用java写的线的缓冲区代码,使用eclipse直接打开就可以使用,这里返回的是经纬度的坐标串,修改传入坐标,直接可以得到线缓冲区的的坐标串,然后再可视化即可。
GIS缓冲区和叠加分析 GIS缓冲区分析算法和 叠加分析算法
arcgis api for js 缓冲区分析。可以直接运行,可以实现,初学者可以下载看看
android 录音,获取录音的音频流数据,放入缓冲区,分析缓冲区的数据.rar,太多无法一一验证是否可用,程序如果跑不起来需要自调,部分代码功能进行参考学习。
三种圆形缓冲的进度条源码.zip
程序包含画点、线、面,以及他们生成缓冲区,可以自己选择缓冲区的半径。点面、线面、面面的叠置分析。
Android模仿乐淘的应用程序分析源码.zip Android游戏源码——忍者快跑.rar Android自动发送短信.rar Android自动开关机实现.rar Android视频采集+RTSP完整代码(可用) Android远程登录含有loading登录效.zip Angle ...