Android screencap的处理流程

以下分析基于Android Q的代码

 

先大体整理screencap的处理流程
1.获取DisplayID
std::optional<PhysicalDisplayId> displayId = SurfaceComposerClient::getInternalDisplayId();

2. 调用ScreenshotClient::capture截取屏幕图像,数据保存在一个GraphicBuffer中

ui::Dataspace outDataspace;
sp<GraphicBuffer> outBuffer;
status_t result = ScreenshotClient::capture(*displayId, &outDataspace, &outBuffer);

3. BInder IPC 呼叫到 SurfaceFlinger::captureScreen

根据DisplayId获取到DisplayDevice信息,width/height/orientation/renderArea

4. 继续呼叫 SurfaceFlinger::captureScreenCommon
createGraphicBuffer

5. 继续调用 SurfaceFlinger::captureScreenImplLocked
找到belongsToDisplay 并判断(layer->isVisible() && layer->isSecure()的情况

6. 继续走到 SurfaceFlinger::renderScreenImplLocked
遍历belongsToDisplay的所有layer ==>layer->prepareClientLayer

7. 使用getRenderEngine().drawLayers 绘制合成到一个GraphicBuffer中
GLESRenderEngine::drawLayers中使用GLES完成图像绘制

大体如上过程screencap中就得到了最后保存屏幕截图的GraphicBuffer,然后利用Skia中的方法经encode保存在PNG图片

 

 

 

 

 

 

 

Android原生recent app机制的重点就是去获取screenshots of each task,具体是去调用 :
WindowManagerService::getTaskSnapshot

TaskSnapshot实际是在TaskSnapshotController中获取的
frameworks/base/services/core/java/com/android/server/wm/TaskSnapshotController.java

 

大体如下流程:
     1. TaskSnapshotController::createTaskSnapshot
     2. SurfaceControl::captureLayers
     经JNI
     3. ScreenshotClient::captureChildLayers
     经binder
     4. SurfaceFlinger::captureLayers
     5. SurfaceFlinger::captureScreenCommon
     6. SurfaceFlinger::captureScreenImplLocked
     7. SurfaceFlinger::renderScreenImplLocked
     8. GLESRenderEngine::drawLayers

处理过程和screencap截取屏幕是类似的,区别在于

screencap:呼叫ScreenshotClient::capture,传递displayId给SurfaceFlinger,会把和这个display相关的layer合成绘制到一张图片

TaskSnapshot: 呼叫ScreenshotClient::captureChildLayers,传递和task相关的layerHandle给SurfaceFlinger,会把和这个layerHandle相关的layers / child layers合成绘制到一张图片

差不多简单理解:

screencap:截取屏幕显示的内容

TaskSnapshot:截取一个apk界面显示的内容

 

但从SurfaceFlinger处理来说基本一致,最终都是通过GPU合成 画到一张图片,数据存到GraphicBuffer中返回给caller。

 

posted on 2022-05-14 14:37  二的次方  阅读(2706)  评论(0编辑  收藏  举报