最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

android 13 systrace/perfetto視角分析SurfaceFlinger中截圖源碼分析

2023-10-06 12:28 作者:千里馬學框架  | 我要投稿

背景:

截圖是一種開發(fā)過程中經(jīng)常遇到的功能,但是這個功能底層是怎么實現(xiàn)的?今天就來給大家分享一下的,截圖的的實現(xiàn)原理。 截圖場景: 一般截圖都有以下幾個方式:

1、音量下鍵+power

2、systemui中下拉狀態(tài)欄,或者關(guān)機選著界面

3、adb shell命令行方式screencap命令方式

主要就是以上幾個,雖然場景不一樣,但是他們最后調(diào)用的截圖接口其實都是同一個,都是最后會調(diào)用到surfaceflinger中的截圖方法,下面就以adb shell命令行方式screencap案例分析,因為他的接口調(diào)用最為簡單,這次分析方式主要是使用perfetto的trace分析方式

screencap命令相關(guān)源碼及抓取perfetto操作

抓取perfetto方式:

1、輸入如下命令進行perfetto抓取

test@test:~$?aosp/external/perfetto/tools/record_android_trace?-o?$(date?+%Y%m%d_%H%M%S)_trace_file.perfetto-trace?-t?5s?-b?32mb?sched?freq?idle?am?wm?gfx?view?binder_driver?hal?dalvik?camera?input?res?memory?gfx?view?wm?am?ss?video?camera?hal?res?sync?idle?binder_driver?binder_lock?ss

2、另一個終端輸入如下命令進行截圖:

screencap -p /sdcard/1.png

代碼位置:

frameworks/base/cmds/screencap/screencap.cpp

int?main(int?argc,?char**?argv)
{
????std::optional<DisplayId>?displayId?=?SurfaceComposerClient::getInternalDisplayId();
???//省略部分
????ProcessState::self()->setThreadPoolMaxThreadCount(0);
????ProcessState::self()->startThreadPool();

????sp<SyncScreenCaptureListener>?captureListener?=?new?SyncScreenCaptureListener();
????//最為核心的方法ScreenshotClient::captureDisplay
????status_t?result?=?ScreenshotClient::captureDisplay(*displayId,?captureListener);
????if?(result?!=?NO_ERROR)?{
????????close(fd);
????????return?1;
????}

????ScreenCaptureResults?captureResults?=?captureListener->waitForResults();
????if?(captureResults.result?!=?NO_ERROR)?{
????????close(fd);
????????return?1;
????}
????ui::Dataspace?dataspace?=?captureResults.capturedDataspace;
????sp<GraphicBuffer>?buffer?=?captureResults.buffer;

????result?=?buffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,?&base);


????if?(png)?{
????????AndroidBitmapInfo?info;
????????info.format?=?flinger2bitmapFormat(buffer->getPixelFormat());
????????info.flags?=?ANDROID_BITMAP_FLAGS_ALPHA_PREMUL;
????????info.width?=?buffer->getWidth();
????????info.height?=?buffer->getHeight();
????????info.stride?=?buffer->getStride()?*?bytesPerPixel(buffer->getPixelFormat());

????????int?result?=?AndroidBitmap_compress(&info,?static_cast<int32_t>(dataspace),?base,
????????????????????????????????????????????ANDROID_BITMAP_COMPRESS_FORMAT_PNG,?100,?&fd,
????????????????????????????????????????????[](void*?fdPtr,?const?void*?data,?size_t?size)?->?bool?{
????????????????????????????????????????????????int?bytesWritten?=?write(*static_cast<int*>(fdPtr),
?????????????????????????????????????????????????????????????????????????data,?size);
????????????????????????????????????????????????return?bytesWritten?==?size;
????????????????????????????????????????????});
????
???//省略部分

????????if?(fn?!=?NULL)?{
????????????notifyMediaScanner(fn);
????????}
????}
?????
???//省略部分
????return?0;
}

其實整個screencap最為核心代碼就是只有一句: ScreenshotClient::captureDisplay 這個就是調(diào)用截圖相關(guān)的接口,該接口實現(xiàn)如下:

status_t?ScreenshotClient::captureDisplay(const?DisplayCaptureArgs&?captureArgs,
??????????????????????????????????????????const?sp<IScreenCaptureListener>&?captureListener)
?
{
????sp<gui::ISurfaceComposer>?s(ComposerServiceAIDL::getComposerService());
????if?(s?==?nullptr)?return?NO_INIT;

????binder::Status?status?=?s->captureDisplay(captureArgs,?captureListener);
????return?status.transactionError();
}

其實本質(zhì)是個跨進程調(diào)用,最后會調(diào)用到surfaceflinger的captureDisplay方法:

status_t?SurfaceFlinger::captureDisplay(DisplayId?displayId,
????????????????????????????????????????const?sp<IScreenCaptureListener>&?captureListener)
?
{
????ui::LayerStack?layerStack;
????wp<const?DisplayDevice>?displayWeak;
????ui::Size?size;
????ui::Dataspace?dataspace;
????{
????????Mutex::Autolock?lock(mStateLock);

????????const?auto?display?=?getDisplayDeviceLocked(displayId);
????????if?(!display)?{
????????????return?NAME_NOT_FOUND;
????????}

????????displayWeak?=?display;
????????layerStack?=?display->getLayerStack();
????????size?=?display->getLayerStackSpaceRect().getSize();

????????dataspace?=
????????????????pickDataspaceFromColorMode(display->getCompositionDisplay()->getState().colorMode);
????}

????RenderAreaFuture?renderAreaFuture?=?ftl::defer([=]?{
????????return?DisplayRenderArea::create(displayWeak,?Rect(),?size,?dataspace,
?????????????????????????????????????????false?/*?useIdentityTransform?*/,
?????????????????????????????????????????false?/*?captureSecureLayers?*/);
????});

????auto?traverseLayers?=?[this,?layerStack](const?LayerVector::Visitor&?visitor)?{
????????traverseLayersInLayerStack(layerStack,?CaptureArgs::UNSET_UID,?visitor);
????};


????auto?future?=?captureScreenCommon(std::move(renderAreaFuture),?traverseLayers,?size,
??????????????????????????????????????ui::PixelFormat::RGBA_8888,?kAllowProtected,?kGrayscale,
??????????????????????????????????????captureListener);
????return?fenceStatus(future.get());
}

結(jié)合trace分析

具體上面的流程進行systrace、perfetto展示如下:

在這里插入圖片描述

這里顯示發(fā)起了一個跨進程調(diào)用,目標段是surfaceflinger進程

在這里插入圖片描述

trace的總結(jié)圖如下:

在這里插入圖片描述

surfaceflinger還有一個額外的回調(diào)客戶端操作:

在這里插入圖片描述

1、準備好buffer來繪制截圖

2、主導surfaceflinger需要相關(guān)的layer預處理

3、使用SkiaGl引擎進行進行相關(guān)的Layer繪制到新buffer

4、通知客戶端,回調(diào)listener


更多干貨內(nèi)容請關(guān)注,及私聊千里馬本人

android 13 systrace/perfetto視角分析SurfaceFlinger中截圖源碼分析的評論 (共 條)

分享到微博請遵守國家法律
留坝县| 内乡县| 灵璧县| 七台河市| 高要市| 仪陇县| 德昌县| 湘阴县| 丁青县| 龙胜| 老河口市| 冀州市| 南城县| 新乡县| 惠东县| 车致| 新竹市| 江口县| 崇左市| 公安县| 桐城市| 陈巴尔虎旗| 仁寿县| 茂名市| 温泉县| 三原县| 北辰区| 托克逊县| 永泰县| 遵义市| 叶城县| 汉沽区| 屯昌县| 保亭| 翁源县| 文昌市| 定远县| 渝北区| 深泽县| 安福县| 启东市|