Android最近任務顯示的圖片

Android最近任務顯示的圖片

  • 1、TaskSnapshot截圖
    • 1.1 snapshotTask
    • 1.2 drawAppThemeSnapshot
  • 2、導航欄顯示問題
  • 3、Recentan按鍵進入最近任務

1、TaskSnapshot截圖

frameworks/base/services/core/java/com/android/server/wm/TaskSnapshotController.java
frameworks/base/core/java/android/view/SurfaceControl.java
frameworks/base/core/jni/android_view_SurfaceControl.cpp
frameworks/native/libs/gui/SurfaceComposerClient.cpp
frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp

截圖保存路徑:data/system_ce/0/snapshots

TaskSnapshot captureTaskSnapshot(Task task, boolean snapshotHome) {final TaskSnapshot snapshot;if (snapshotHome) {snapshot = snapshotTask(task);} else {switch (getSnapshotMode(task)) {case SNAPSHOT_MODE_NONE:return null;case SNAPSHOT_MODE_APP_THEME:snapshot = drawAppThemeSnapshot(task);break;case SNAPSHOT_MODE_REAL:snapshot = snapshotTask(task);break;default:snapshot = null;break;}}return snapshot;
}

1.1 snapshotTask

SNAPSHOT_MODE_REAL:截圖一張真實的屏幕截圖作為快照。
實際截圖緩存 SurfaceControl.captureLayersExcluding -> ScreenshotClient::captureLayers -> SurfaceFlinger::captureLayers

TaskSnapshot snapshotTask(Task task, int pixelFormat) {TaskSnapshot.Builder builder = new TaskSnapshot.Builder();if (!prepareTaskSnapshot(task, pixelFormat, builder)) {// Failed some pre-req. Has been logged.return null;}final SurfaceControl.ScreenshotHardwareBuffer screenshotBuffer =createTaskSnapshot(task, builder);if (screenshotBuffer == null) {// Failed to acquire image. Has been logged.return null;}builder.setSnapshot(screenshotBuffer.getHardwareBuffer());builder.setColorSpace(screenshotBuffer.getColorSpace());return builder.build();
}SurfaceControl.ScreenshotHardwareBuffer createTaskSnapshot(@NonNull Task task,TaskSnapshot.Builder builder) {Point taskSize = new Point();final SurfaceControl.ScreenshotHardwareBuffer taskSnapshot = createTaskSnapshot(task,mHighResTaskSnapshotScale, builder.getPixelFormat(), taskSize, builder);builder.setTaskSize(taskSize);return taskSnapshot;
}SurfaceControl.ScreenshotHardwareBuffer createTaskSnapshot(@NonNull Task task,float scaleFraction, int pixelFormat, Point outTaskSize, TaskSnapshot.Builder builder) {if (task.getSurfaceControl() == null) {if (DEBUG_SCREENSHOT) {Slog.w(TAG_WM, "Failed to take screenshot. No surface control for " + task);}return null;}task.getBounds(mTmpRect);mTmpRect.offsetTo(0, 0);SurfaceControl[] excludeLayers;final WindowState imeWindow = task.getDisplayContent().mInputMethodWindow;// Exclude IME window snapshot when IME isn't proper to attach to app.final boolean excludeIme = imeWindow != null && imeWindow.getSurfaceControl() != null&& !task.getDisplayContent().shouldImeAttachedToApp();final WindowState navWindow =task.getDisplayContent().getDisplayPolicy().getNavigationBar();// If config_attachNavBarToAppDuringTransition is true, the nav bar will be reparent to the// the swiped app when entering recent app, therefore the task will contain the navigation// bar and we should exclude it from snapshot.final boolean excludeNavBar = navWindow != null;if (excludeIme && excludeNavBar) {excludeLayers = new SurfaceControl[2];excludeLayers[0] = imeWindow.getSurfaceControl();excludeLayers[1] = navWindow.getSurfaceControl();} else if (excludeIme || excludeNavBar) {excludeLayers = new SurfaceControl[1];excludeLayers[0] =excludeIme ? imeWindow.getSurfaceControl() : navWindow.getSurfaceControl();} else {excludeLayers = new SurfaceControl[0];}builder.setHasImeSurface(!excludeIme && imeWindow != null && imeWindow.isVisible());final SurfaceControl.ScreenshotHardwareBuffer screenshotBuffer =SurfaceControl.captureLayersExcluding(task.getSurfaceControl(), mTmpRect, scaleFraction,pixelFormat, excludeLayers);if (outTaskSize != null) {outTaskSize.x = mTmpRect.width();outTaskSize.y = mTmpRect.height();}final HardwareBuffer buffer = screenshotBuffer == null ? null: screenshotBuffer.getHardwareBuffer();if (isInvalidHardwareBuffer(buffer)) {return null;}return screenshotBuffer;
}

frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp

status_t SurfaceFlinger::captureLayers(const LayerCaptureArgs& args,const sp<IScreenCaptureListener>& captureListener) {ATRACE_CALL();status_t validate = validateScreenshotPermissions(args);if (validate != OK) {return validate;}ui::Size reqSize;sp<Layer> parent;Rect crop(args.sourceCrop);std::unordered_set<sp<Layer>, SpHash<Layer>> excludeLayers;ui::Dataspace dataspace;// Call this before holding mStateLock to avoid any deadlocking.bool canCaptureBlackoutContent = hasCaptureBlackoutContentPermission();{Mutex::Autolock lock(mStateLock);parent = fromHandle(args.layerHandle).promote();if (parent == nullptr) {ALOGE("captureLayers called with an invalid or removed parent");return NAME_NOT_FOUND;}if (!canCaptureBlackoutContent &&parent->getDrawingState().flags & layer_state_t::eLayerSecure) {ALOGW("Attempting to capture secure layer: PERMISSION_DENIED");return PERMISSION_DENIED;}Rect parentSourceBounds = parent->getCroppedBufferSize(parent->getDrawingState());if (args.sourceCrop.width() <= 0) {crop.left = 0;crop.right = parentSourceBounds.getWidth();}if (args.sourceCrop.height() <= 0) {crop.top = 0;crop.bottom = parentSourceBounds.getHeight();}if (crop.isEmpty() || args.frameScaleX <= 0.0f || args.frameScaleY <= 0.0f) {// Error out if the layer has no source bounds (i.e. they are boundless) and a source// crop was not specified, or an invalid frame scale was provided.return BAD_VALUE;}reqSize = ui::Size(crop.width() * args.frameScaleX, crop.height() * args.frameScaleY);for (const auto& handle : args.excludeHandles) {sp<Layer> excludeLayer = fromHandle(handle).promote();if (excludeLayer != nullptr) {excludeLayers.emplace(excludeLayer);} else {ALOGW("Invalid layer handle passed as excludeLayer to captureLayers");return NAME_NOT_FOUND;}}// The dataspace is depended on the color mode of display, that could use non-native mode// (ex. displayP3) to enhance the content, but some cases are checking native RGB in bytes,// and failed if display is not in native mode. This provide a way to force using native// colors when capture.dataspace = args.dataspace;} // mStateLock// really small crop or frameScaleif (reqSize.width <= 0 || reqSize.height <= 0) {ALOGW("Failed to captureLayes: crop or scale too small");return BAD_VALUE;}Rect layerStackSpaceRect(0, 0, reqSize.width, reqSize.height);bool childrenOnly = args.childrenOnly;RenderAreaFuture renderAreaFuture = ftl::defer([=]() -> std::unique_ptr<RenderArea> {return std::make_unique<LayerRenderArea>(*this, parent, crop, reqSize, dataspace,childrenOnly, layerStackSpaceRect,args.captureSecureLayers);});auto traverseLayers = [parent, args, excludeLayers](const LayerVector::Visitor& visitor) {parent->traverseChildrenInZOrder(LayerVector::StateSet::Drawing, [&](Layer* layer) {if (!layer->isVisible()) {return;} else if (args.childrenOnly && layer == parent.get()) {return;} else if (args.uid != CaptureArgs::UNSET_UID && args.uid != layer->getOwnerUid()) {return;}sp<Layer> p = layer;while (p != nullptr) {if (excludeLayers.count(p) != 0) {return;}p = p->getParent();}visitor(layer);});};if (captureListener == nullptr) {ALOGE("capture screen must provide a capture listener callback");return BAD_VALUE;}auto future = captureScreenCommon(std::move(renderAreaFuture), traverseLayers, reqSize,args.pixelFormat, args.allowProtected, args.grayscale,captureListener);return fenceStatus(future.get());
}

1.2 drawAppThemeSnapshot

SNAPSHOT_MODE_APP_THEME:不允許截圖真實的屏幕截圖,但我們應該嘗試使用應用程序主題來創建應用程序的虛假表示。

/*** If we are not allowed to take a real screenshot, this attempts to represent the app as best* as possible by using the theme's window background.*/
private TaskSnapshot drawAppThemeSnapshot(Task task) {final ActivityRecord topChild = task.getTopMostActivity();if (topChild == null) {return null;}final WindowState mainWindow = topChild.findMainWindow();if (mainWindow == null) {return null;}final int color = ColorUtils.setAlphaComponent(task.getTaskDescription().getBackgroundColor(), 255);final LayoutParams attrs = mainWindow.getAttrs();final Rect taskBounds = task.getBounds();final InsetsState insetsState = mainWindow.getInsetsStateWithVisibilityOverride();final Rect systemBarInsets = getSystemBarInsets(mainWindow.getFrame(), insetsState);final SystemBarBackgroundPainter decorPainter = new SystemBarBackgroundPainter(attrs.flags,attrs.privateFlags, attrs.insetsFlags.appearance, task.getTaskDescription(),mHighResTaskSnapshotScale, insetsState);final int taskWidth = taskBounds.width();final int taskHeight = taskBounds.height();final int width = (int) (taskWidth * mHighResTaskSnapshotScale);final int height = (int) (taskHeight * mHighResTaskSnapshotScale);final RenderNode node = RenderNode.create("TaskSnapshotController", null);node.setLeftTopRightBottom(0, 0, width, height);node.setClipToBounds(false);final RecordingCanvas c = node.start(width, height);c.drawColor(color);decorPainter.setInsets(systemBarInsets);decorPainter.drawDecors(c /* statusBarExcludeFrame */);node.end(c);final Bitmap hwBitmap = ThreadedRenderer.createHardwareBitmap(node, width, height);if (hwBitmap == null) {return null;}final Rect contentInsets = new Rect(systemBarInsets);final Rect letterboxInsets = topChild.getLetterboxInsets();InsetUtils.addInsets(contentInsets, letterboxInsets);// Note, the app theme snapshot is never translucent because we enforce a non-translucent// color abovereturn new TaskSnapshot(System.currentTimeMillis() /* id */,topChild.mActivityComponent, hwBitmap.getHardwareBuffer(),hwBitmap.getColorSpace(), mainWindow.getConfiguration().orientation,mainWindow.getWindowConfiguration().getRotation(), new Point(taskWidth, taskHeight),contentInsets, letterboxInsets, false /* isLowResolution */,false /* isRealSnapshot */, task.getWindowingMode(),getAppearance(task), false /* isTranslucent */, false /* hasImeSurface */);
}

2、導航欄顯示問題

應用設置導航欄可避免圖片底部黑條

<item name="android:enforceNavigationBarContrast">false</item>
<item name="android:navigationBarColor">@android:color/transparent</item>

3、Recentan按鍵進入最近任務

<!-- Component name for the activity that will be presenting the Recents UI, which will receivespecial permissions for API related to fetching and presenting recent tasks. The defaultconfiguration uses Launcehr3QuickStep as default launcher and points to the correspondingrecents component. When using a different default launcher, change this appropriately oruse the default systemui implementation: com.android.systemui/.recents.RecentsActivity -->
<string name="config_recentsComponentName" translatable="false">com.android.launcher3/com.android.quickstep.RecentsActivity</string>

在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/41112.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/41112.shtml
英文地址,請注明出處:http://en.pswp.cn/web/41112.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

IPython 性能評估工具的較量:%%timeit 與 %timeit 的差異解析

IPython 性能評估工具的較量&#xff1a;%%timeit 與 %timeit 的差異解析 在 IPython 的世界中&#xff0c;性能評估是一項至關重要的任務。%%timeit 和 %timeit 是兩個用于測量代碼執行時間的魔術命令&#xff0c;但它們之間存在一些關鍵的差異。本文將深入探討這兩個命令的不…

2786. 訪問數組中的位置使分數最大

2786. 訪問數組中的位置使分數最大 題目鏈接&#xff1a;2786. 訪問數組中的位置使分數最大 代碼如下&#xff1a; //參考鏈接:https://leetcode.cn/problems/visit-array-positions-to-maximize-score/solutions/2810335/dp-by-kkkk-16-tn9f class Solution { public:long …

vue-router 4匯總

一、vue和vue-router版本&#xff1a; "vue": "^3.4.29", "vue-router": "^4.4.0" 二、路由傳參&#xff1a; 方式一&#xff1a; 路由配置&#xff1a;/src/router/index.ts import {createRouter,createWebHistory } from &quo…

探索 WebKit 的緩存迷宮:深入理解其高效緩存機制

探索 WebKit 的緩存迷宮&#xff1a;深入理解其高效緩存機制 在當今快速變化的網絡世界中&#xff0c;WebKit 作為領先的瀏覽器引擎之一&#xff0c;其緩存機制對于提升網頁加載速度、減少服務器負載以及改善用戶體驗起著至關重要的作用。本文將深入探討 WebKit 的緩存機制&am…

代碼隨想錄leetcode200題之額外題目

目錄 1 介紹2 訓練3 參考 1 介紹 本博客用來記錄代碼隨想錄leetcode200題之額外題目相關題目。 2 訓練 題目1&#xff1a;1365. 有多少小于當前數字的數字 解題思路&#xff1a;二分查找。 C代碼如下&#xff0c; class Solution { public:vector<int> smallerNumb…

卷積神經網絡(CNN)和循環神經網絡(RNN) 的區別與聯系

卷積神經網絡&#xff08;CNN&#xff09;和循環神經網絡&#xff08;RNN&#xff09;是兩種廣泛應用于深度學習的神經網絡架構&#xff0c;它們在設計理念和應用領域上有顯著區別&#xff0c;但也存在一些聯系。 ### 卷積神經網絡&#xff08;CNN&#xff09; #### 主要特點…

解決C++編譯時的產生的skipping incompatible xxx 錯誤

問題 我在編譯項目時&#xff0c;產生了一個 /usr/bin/ld: skipping incompatible ../../xxx/ when searching for -lxxx 的編譯錯誤&#xff0c;如下圖所示&#xff1a; 解決方法 由圖中的錯誤可知&#xff0c;在編譯時&#xff0c;是能夠在我們指定目錄下的 *.so 動態庫的…

python函數和c的區別有哪些

Python有很多內置函數&#xff08;build in function&#xff09;&#xff0c;不需要寫頭文件&#xff0c;Python還有很多強大的模塊&#xff0c;需要時導入便可。C語言在這一點上遠不及Python&#xff0c;大多時候都需要自己手動實現。 C語言中的函數&#xff0c;有著嚴格的順…

Java基礎(六)——繼承

個人簡介 &#x1f440;個人主頁&#xff1a; 前端雜貨鋪 ?開源項目&#xff1a; rich-vue3 &#xff08;基于 Vue3 TS Pinia Element Plus Spring全家桶 MySQL&#xff09; &#x1f64b;?♂?學習方向&#xff1a; 主攻前端方向&#xff0c;正逐漸往全干發展 &#x1…

【Web】

1、配倉庫 [rootlocalhost yum.repos.d]# vi rpm.repo ##本地倉庫標準寫法 [baseos] namemiaoshubaseos baseurl/mnt/BaseOS gpgcheck0 [appstream] namemiaoshuappstream baseurlfile:///mnt/AppStream gpgcheck0 2、掛載 [rootlocalhost ~]mount /dev/sr0 /mnt mount: /m…

QT操作各類數據庫用法詳解

文章目錄 創建內存SQLITE數據庫QSqlTableModel操作數據庫表連接國產數據庫多線程數據處理不指定數據庫名打開數據庫QT對各種數據庫的支持情況處理數據庫表名QT連接各種數據庫Qt提供了一個名為QtSQL模塊的強大組件, 使得在Qt應用程序中連接和操作多種類型的數據庫變得相對簡單。…

Vulnhub-Os-hackNos-1(包含靶機獲取不了IP地址)

https://download.vulnhub.com/hacknos/Os-hackNos-1.ova #靶機下載地址 題目&#xff1a;要找到兩個flag user.txt root.txt 文件打開 改為NAT vuln-hub-OS-HACKNOS-1靶機檢測不到IP地址 重啟靶機 按住shift 按下鍵盤字母"E"鍵 將圖中ro修改成…

Github 2024-07-06 開源項目日報 Top10

根據Github Trendings的統計,今日(2024-07-06統計)共有10個項目上榜。根據開發語言中項目的數量,匯總情況如下: 開發語言項目數量Python項目3TypeScript項目2Rust項目2非開發語言項目1C++項目1QML項目1MDX項目1JavaScript項目1Assembly項目1免費編程書籍和學習資源清單 創建…

JS 四舍五入使用整理

一、Number.toFixed() 把數字轉換為字符串,結果的小數點后有指定位數的數字,重點返回的數據類型為字符串 toFixed() 方法將一個浮點數轉換為指定小數位數的字符串表示,如果小數位數高于數字,則使用 0 來填充。 toFixed() 方法可把 Number 四舍五入為指定小數位數的數字。…

Vue 3集成krpano 全景圖展示

Vue 3集成krpano 全景圖展示 星光云全景系統源碼 VR全景體驗地址 星光云全景VR系統 將全景krpano靜態資源文件vtour放入vue項目中 導入vue之前需要自己制作一個全景圖 需要借助官方工具進行制作 工具下載地址&#xff1a;krpano工具下載地址 注意事項&#xff1a;vuecli…

Hook 實現 Windows 系統熱鍵屏蔽(二)

目錄 前言 一、介紹用戶賬戶控制&#xff08;UAC&#xff09; 1.1 什么是 UAC &#xff1f; 2.2 UAC 運行機制的概述 2.3 分析 UAC 提權參數 二、 NdrAsyncServerCall 函數的分析 2.1 函數聲明的解析 2.2 對 Winlogon 的逆向 2.3 對 rpcrt4 的靜態分析 2.4 對 rpcrt4…

YOLOv8_obb數據集可視化[旋轉目標檢測實踐篇]

先貼代碼,周末再補充解析。 這個篇章主要是對標注好的標簽進行可視化,雖然比較簡單,但是可以從可視化代碼中學習到YOLOv8是如何對標簽進行解析的。 import cv2 import numpy as np import os import randomdef read_obb_labels(label_file_path):with open(label_file_path,…

探索 IPython 的環境感知能力:詳解 %env 命令的妙用

探索 IPython 的環境感知能力&#xff1a;詳解 %env 命令的妙用 在數據科學和編程的海洋中&#xff0c;環境變量扮演著至關重要的角色。IPython&#xff0c;這一強大的交互式計算工具&#xff0c;通過其內置的魔術命令 %env&#xff0c;為我們提供了與環境變量交互的強大能力。…

git基礎指令總結持續更新之git分支簡介和基本操作,解決合并和沖突,回退和rebase(變基),分支命名和分支管理,學習筆記分享

git 分支簡介和基本操作 Git 分支是 Git 的核心特性之一&#xff0c;它允許開發者在不同的開發線上工作&#xff0c;而不會影響主代碼庫。以下是 Git 分支的簡介和一些基本操作&#xff1a; 分支的概念&#xff1a; 分支是 Git 中的一個獨立開發線。創建分支時&#xff0c;G…

rtt設備驅動框架學習——內核對象基類object

內核對象基類object 這個基類是內核所有對象的基類 在rt-thread/include/rtdef.h文件里有對內核對象基類object的定義 /*** Base structure of Kernel object*/ struct rt_object {char name[RT_NAME_MAX]; /**< name of kernel object */rt…