首页 » 未分类 » 【源码解读】Screencap源码分析-基础篇

【源码解读】Screencap源码分析-基础篇

 

本文期望达到的目的:

  1. 了解screencap使用
  2. 了解screencap实现基础原理
  3. 为后续screencap源码修改和其他应用做准备

源码位置:

android4.0之后内置了截图工具screencap,一般位于/system/bin/screencap

源码路径:frameworks/base/cmds/screencap/

使用介绍:

帮助文档:

usage: screencap [-hp] [-d display-id] [FILENAME]  
   -h: this message
   -p: save the file as a png.
   -d: specify the display id to capture, default 0.
If FILENAME ends with .png it will be saved as a png.
If FILENAME is not given, the results will be printed to stdout.

使用相当简单:

adb shell screencap -p/sdcard/testscreen.png

备注:

  1. -d 参数为支持扩展的display设备
  2. 如果文件名以.png结尾时,它将保存为png文件,如果文件名没有给出,则结果被会被输出到stdout(导出会相当的卡)

如果手机没有连接adb,我们也可以用以下代码去完成调用:

6

源码分析:

核心代码:

1

整个程序最核心的代码就是上图。

获取截图信息的流程是通过ScreenshotClient对象,如果发现ScreenshotClient获取失败则读取/dev/graphics/fb0文件。

不知道/dev/graphics/fb0是什么文件,可以google下。

1、 fb0读取比较容易看懂:(如果有兴趣的话可以继续去看linux内核文件中的显示文件)

  1. 直接open()打开文件
  2. 通过fb_var_screeninfo结构体来定位fb0的文件头格式
  3. 根据偏移地址把一贞的数据读到一个mmap中,
  4. base = (void const *)((char const *)mapbase + offset);

2、ScreenshotClient:

  1. 创建ScreenshotClient screenshot
  2. 直接调用screenshot.update()
  3. base = screenshot.getPixels();

后续我们再继续阅读ScreenshotClient类,了解它是如何显示屏幕显示获取的:

ScreenshotClient类位于frameworks/native/libs/gui/SurfaceComposerClient.cpp中。

这个类提供了updata()函数:

2

从567行来看,该函数是直接调用了SurfaceFlinger服务的代理对象中的captureScreen()函数。

其中getComposerService()函数的源码:

3

从代码上可以看出,instance.mComposerService是SurfaceFlinger服务的代理对象。

如果有兴趣的话可以继续跟进去里面的代码,会发现上面的第5行代码就是通过getService("SurfaceFlinger", &mComposerService)获取服务代理对象。

说到“SurfaceFlinger”服务,这个服务器是比较庞大的架构。主要的作用是进行UI绘制。(后续可以深入分析)

所以:

    Screencap的实现就是通过访问“SurfaceFlinger”服务或者读取fb0文件进行截屏的。

最后我们看看Screencap保存图片的代码:

4

程序只提供了png后缀的图片格式,如果想要返回其他的图片格式,需要要进行类型type的修改。

图片格式:

1、SkImageEncoder 中的Type 枚举(注意有些android版本是没有完全实现的)

5

2、kDefaultQuality默认值为80 图片的清晰度

如果想提高这个工具的截屏效率,可以通过选择图片格式或者选择图片的质量。

总结:

  1. 经实际测试,1s 不到10帧,screencap效率是相当差的(包含保存为jpeg等格式)。
  2. 如果需要修改保存图片的格式,需要修改源码重新编译。

原文链接:【源码解读】Screencap源码分析-基础篇,转载请注明来源!

1